@webiny/api-headless-cms-ddb 5.17.4 → 5.18.0-beta.3

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 (91) hide show
  1. package/definitions/entry.d.ts +6 -4
  2. package/definitions/entry.js +19 -8
  3. package/definitions/group.d.ts +8 -0
  4. package/definitions/group.js +74 -0
  5. package/definitions/model.d.ts +8 -0
  6. package/definitions/model.js +96 -0
  7. package/definitions/settings.d.ts +8 -0
  8. package/definitions/settings.js +62 -0
  9. package/definitions/system.d.ts +8 -0
  10. package/definitions/system.js +50 -0
  11. package/definitions/table.d.ts +6 -12
  12. package/definitions/table.js +15 -15
  13. package/dynamoDb/index.d.ts +1 -1
  14. package/dynamoDb/index.js +4 -3
  15. package/dynamoDb/path/plainObject.js +1 -2
  16. package/dynamoDb/path/ref.js +1 -2
  17. package/dynamoDb/storage/date.d.ts +2 -2
  18. package/dynamoDb/storage/date.js +17 -21
  19. package/dynamoDb/storage/longText.d.ts +7 -0
  20. package/dynamoDb/storage/longText.js +83 -0
  21. package/dynamoDb/storage/richText.d.ts +2 -2
  22. package/dynamoDb/storage/richText.js +69 -67
  23. package/dynamoDb/transformValue/datetime.d.ts +1 -1
  24. package/dynamoDb/transformValue/datetime.js +1 -2
  25. package/index.d.ts +2 -6
  26. package/index.js +108 -13
  27. package/operations/entry/dataLoaders.d.ts +34 -19
  28. package/operations/entry/dataLoaders.js +158 -138
  29. package/operations/entry/index.d.ts +8 -4
  30. package/operations/entry/index.js +812 -16
  31. package/operations/entry/keys.d.ts +25 -0
  32. package/operations/entry/keys.js +62 -0
  33. package/operations/entry/systemFields.d.ts +2 -2
  34. package/operations/entry/systemFields.js +1 -2
  35. package/operations/entry/utils.d.ts +13 -9
  36. package/operations/entry/utils.js +62 -18
  37. package/operations/group/index.d.ts +8 -0
  38. package/operations/group/index.js +198 -0
  39. package/operations/model/index.d.ts +6 -3
  40. package/operations/model/index.js +153 -18
  41. package/operations/settings/index.d.ts +6 -3
  42. package/operations/settings/index.js +132 -16
  43. package/operations/system/index.d.ts +6 -3
  44. package/operations/system/index.js +94 -14
  45. package/package.json +11 -11
  46. package/types.d.ts +38 -8
  47. package/types.js +11 -1
  48. package/configurations.d.ts +0 -18
  49. package/configurations.js +0 -24
  50. package/configurations.js.map +0 -1
  51. package/definitions/entry.js.map +0 -1
  52. package/definitions/table.js.map +0 -1
  53. package/dynamoDb/index.js.map +0 -1
  54. package/dynamoDb/path/plainObject.js.map +0 -1
  55. package/dynamoDb/path/ref.js.map +0 -1
  56. package/dynamoDb/storage/date.js.map +0 -1
  57. package/dynamoDb/storage/richText.js.map +0 -1
  58. package/dynamoDb/transformValue/datetime.js.map +0 -1
  59. package/index.js.map +0 -1
  60. package/operations/entry/CmsContentEntryDynamo.d.ts +0 -86
  61. package/operations/entry/CmsContentEntryDynamo.js +0 -972
  62. package/operations/entry/CmsContentEntryDynamo.js.map +0 -1
  63. package/operations/entry/dataLoaders.js.map +0 -1
  64. package/operations/entry/index.js.map +0 -1
  65. package/operations/entry/systemFields.js.map +0 -1
  66. package/operations/entry/utils.js.map +0 -1
  67. package/operations/helpers.d.ts +0 -5
  68. package/operations/helpers.js +0 -96
  69. package/operations/helpers.js.map +0 -1
  70. package/operations/model/CmsContentModelDynamo.d.ts +0 -18
  71. package/operations/model/CmsContentModelDynamo.js +0 -234
  72. package/operations/model/CmsContentModelDynamo.js.map +0 -1
  73. package/operations/model/index.js.map +0 -1
  74. package/operations/modelGroup/CmsContentModelGroupDynamo.d.ts +0 -42
  75. package/operations/modelGroup/CmsContentModelGroupDynamo.js +0 -230
  76. package/operations/modelGroup/CmsContentModelGroupDynamo.js.map +0 -1
  77. package/operations/modelGroup/index.d.ts +0 -3
  78. package/operations/modelGroup/index.js +0 -26
  79. package/operations/modelGroup/index.js.map +0 -1
  80. package/operations/settings/CmsSettingsDynamo.d.ts +0 -16
  81. package/operations/settings/CmsSettingsDynamo.js +0 -145
  82. package/operations/settings/CmsSettingsDynamo.js.map +0 -1
  83. package/operations/settings/index.js.map +0 -1
  84. package/operations/system/CmsSystemDynamo.d.ts +0 -16
  85. package/operations/system/CmsSystemDynamo.js +0 -126
  86. package/operations/system/CmsSystemDynamo.js.map +0 -1
  87. package/operations/system/index.js.map +0 -1
  88. package/types.js.map +0 -1
  89. package/utils.d.ts +0 -5
  90. package/utils.js +0 -62
  91. package/utils.js.map +0 -1
@@ -1,972 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.TYPE_ENTRY_PUBLISHED = exports.TYPE_ENTRY_LATEST = exports.TYPE_ENTRY = exports.CmsContentEntryDynamo = void 0;
9
-
10
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
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("@webiny/api-headless-cms/utils");
19
-
20
- var _utils2 = require("../../utils");
21
-
22
- var _utils3 = require("./utils");
23
-
24
- var _lodash = _interopRequireDefault(require("lodash.clonedeep"));
25
-
26
- var _entry = require("../../definitions/entry");
27
-
28
- var _table = require("../../definitions/table");
29
-
30
- 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; }
31
-
32
- 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; }
33
-
34
- const TYPE_ENTRY = "cms.entry";
35
- exports.TYPE_ENTRY = TYPE_ENTRY;
36
- const TYPE_ENTRY_LATEST = TYPE_ENTRY + ".l";
37
- exports.TYPE_ENTRY_LATEST = TYPE_ENTRY_LATEST;
38
- const TYPE_ENTRY_PUBLISHED = TYPE_ENTRY + ".p";
39
- exports.TYPE_ENTRY_PUBLISHED = TYPE_ENTRY_PUBLISHED;
40
- const GSI1_INDEX = "GSI1";
41
- const configurationDefaults = {
42
- defaultLimit: 100,
43
- maxLimit: undefined
44
- };
45
- /**
46
- * We do not use transactions in this storage operations implementation due to their cost.
47
- */
48
-
49
- class CmsContentEntryDynamo {
50
- get context() {
51
- return this._context;
52
- }
53
-
54
- get configuration() {
55
- return this._configuration;
56
- }
57
-
58
- get table() {
59
- return this._table;
60
- }
61
-
62
- get entity() {
63
- return this._entity;
64
- }
65
-
66
- constructor({
67
- context,
68
- configuration
69
- }) {
70
- (0, _defineProperty2.default)(this, "_context", void 0);
71
- (0, _defineProperty2.default)(this, "_configuration", void 0);
72
- (0, _defineProperty2.default)(this, "_modelPartitionKey", void 0);
73
- (0, _defineProperty2.default)(this, "_dataLoaders", void 0);
74
- (0, _defineProperty2.default)(this, "_table", void 0);
75
- (0, _defineProperty2.default)(this, "_entity", void 0);
76
- this._context = context;
77
- this._configuration = _objectSpread(_objectSpread({}, configurationDefaults), configuration || {});
78
- this._modelPartitionKey = `${this.partitionKey}#M`;
79
- this._dataLoaders = new _dataLoaders.DataLoadersHandler(context, this);
80
- this._table = (0, _table.createTable)({
81
- context,
82
- indexes: {
83
- [GSI1_INDEX]: {
84
- partitionKey: "GSI1_PK",
85
- sortKey: "GSI1_SK"
86
- }
87
- }
88
- });
89
- this._entity = (0, _entry.createEntryEntity)({
90
- table: this._table
91
- });
92
- }
93
-
94
- async create(model, args) {
95
- const {
96
- entry,
97
- storageEntry
98
- } = args;
99
- const partitionKey = this.getPartitionKey(entry.id);
100
- /**
101
- * We need to:
102
- * - create new main entry item
103
- * - create new or update latest entry item
104
- */
105
-
106
- const items = [this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
107
- PK: partitionKey,
108
- SK: this.getSortKeyRevision(entry.version),
109
- TYPE: TYPE_ENTRY,
110
- GSI1_PK: this.getGSIEntryPartitionKey(model),
111
- GSI1_SK: this.getGSISortKey(storageEntry)
112
- })), this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
113
- PK: partitionKey,
114
- SK: this.getSortKeyLatest(),
115
- TYPE: TYPE_ENTRY_LATEST,
116
- GSI1_PK: this.getGSILatestPartitionKey(model),
117
- GSI1_SK: this.getGSISortKey(storageEntry)
118
- }))];
119
-
120
- try {
121
- await this._table.batchWrite(items);
122
- } catch (ex) {
123
- throw new _error.default(ex.message || "Could not insert data into the DynamoDB.", ex.code || "CREATE_ENTRY_ERROR", {
124
- error: ex,
125
- entry
126
- });
127
- }
128
-
129
- return storageEntry;
130
- }
131
-
132
- async createRevisionFrom(model, args) {
133
- const {
134
- originalEntry,
135
- entry,
136
- storageEntry,
137
- latestEntry
138
- } = args;
139
- const partitionKey = this.getPartitionKey(storageEntry.id);
140
- /**
141
- * We need to:
142
- * - create the main entry item
143
- * - update the last entry item to a current one
144
- */
145
-
146
- const items = [this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
147
- PK: partitionKey,
148
- SK: this.getSortKeyRevision(storageEntry.version),
149
- TYPE: TYPE_ENTRY,
150
- GSI1_PK: this.getGSIEntryPartitionKey(model),
151
- GSI1_SK: this.getGSISortKey(storageEntry)
152
- })), this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
153
- PK: partitionKey,
154
- SK: this.getSortKeyLatest(),
155
- TYPE: TYPE_ENTRY_LATEST,
156
- GSI1_PK: this.getGSILatestPartitionKey(model),
157
- GSI1_SK: this.getGSISortKey(storageEntry)
158
- }))];
159
-
160
- try {
161
- await this._table.batchWrite(items);
162
- } catch (ex) {
163
- throw new _error.default(ex.message || "Could not create revision from given entry.", ex.code || "CREATE_REVISION_ERROR", {
164
- error: ex,
165
- originalEntry,
166
- latestEntry,
167
- entry,
168
- storageEntry
169
- });
170
- }
171
- /**
172
- * There are no modifications on the entry created so just return the data.
173
- */
174
-
175
-
176
- return storageEntry;
177
- }
178
-
179
- async delete(model, args) {
180
- const {
181
- entry
182
- } = args;
183
- const partitionKey = this.getPartitionKey(entry.id);
184
- const results = await this._entity.query(partitionKey, {
185
- gte: " "
186
- });
187
- const keys = results.Items.map(item => ({
188
- PK: partitionKey,
189
- SK: item.SK
190
- }));
191
-
192
- try {
193
- await this._table.batchWrite(keys.map(key => this._entity.deleteBatch(key)));
194
- } catch (ex) {
195
- throw new _error.default(ex.message || "Could not delete the entry.", ex.code || "DELETE_ENTRY_ERROR", {
196
- error: ex,
197
- partitionKey,
198
- keys
199
- });
200
- }
201
- }
202
-
203
- async deleteRevision(model, args) {
204
- const {
205
- entryToDelete,
206
- entryToSetAsLatest,
207
- storageEntryToSetAsLatest
208
- } = args;
209
- const partitionKey = this.getPartitionKey(entryToDelete.id);
210
- const items = [this._entity.deleteBatch({
211
- PK: partitionKey,
212
- SK: this.getSortKeyRevision(entryToDelete.id)
213
- })];
214
- const publishedStorageEntry = await this.getPublishedRevisionByEntryId(model, entryToDelete.id);
215
- /**
216
- * If revision we are deleting is the published one as well, we need to delete those records as well.
217
- */
218
-
219
- if (publishedStorageEntry && entryToDelete.id === publishedStorageEntry.id) {
220
- items.push(this._entity.deleteBatch({
221
- PK: partitionKey,
222
- SK: this.getSortKeyPublished()
223
- }));
224
- }
225
-
226
- if (storageEntryToSetAsLatest) {
227
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntryToSetAsLatest), {}, {
228
- PK: partitionKey,
229
- SK: this.getSortKeyLatest(),
230
- TYPE: TYPE_ENTRY_LATEST,
231
- GSI1_PK: this.getGSILatestPartitionKey(model),
232
- GSI1_SK: this.getGSISortKey(storageEntryToSetAsLatest)
233
- })));
234
- }
235
-
236
- try {
237
- await this._table.batchWrite(items);
238
- } catch (ex) {
239
- throw new _error.default(ex.message, ex.code, {
240
- error: ex,
241
- entryToDelete,
242
- entryToSetAsLatest
243
- });
244
- }
245
- }
246
-
247
- async get(model, args) {
248
- const {
249
- items
250
- } = await this.list(model, _objectSpread(_objectSpread({}, args || {}), {}, {
251
- limit: 1
252
- }));
253
-
254
- if (items.length === 0) {
255
- return null;
256
- }
257
-
258
- return items.shift();
259
- }
260
-
261
- async list(model, args) {
262
- const {
263
- limit: initialLimit,
264
- where: originalWhere,
265
- after,
266
- sort
267
- } = args;
268
- /**
269
- * There is no max limit imposed because that is up to the devs using this.
270
- * Default is some reasonable number for us but users can set their own when initializing the plugin.
271
- */
272
-
273
- const defaultLimit = this.configuration.defaultLimit || configurationDefaults.defaultLimit;
274
- const maxLimit = this.configuration.maxLimit || defaultLimit;
275
- const limit = !initialLimit || initialLimit <= 0 ? initialLimit > maxLimit ? maxLimit : defaultLimit : initialLimit;
276
- const items = [];
277
- const queryOptions = this.createQueryOptions({
278
- where: originalWhere,
279
- model
280
- });
281
-
282
- try {
283
- /**
284
- * We run the query method on all the partition keys that were built in the createQueryOptions() method.
285
- * Partition keys are always built as array because of the possibility that we might need to read from different partitions
286
- * which is the case if where condition is something like id_in or entryId_in.
287
- * If we are reading from the GSI1_PK it is a single partition but we keep it as an array
288
- * just to make it easier to read in all of the cases.
289
- */
290
- for (const partitionKey of queryOptions.queryPartitionKeys) {
291
- const results = await this.runQuery({
292
- partitionKey,
293
- options: queryOptions.options
294
- });
295
- items.push(...results);
296
- }
297
- } catch (ex) {
298
- throw new _error.default(ex.message, "SCAN_ERROR", {
299
- error: ex
300
- });
301
- }
302
- /**
303
- * We need a object containing field, transformers and paths.
304
- * Just build it here and pass on into other methods that require it to avoid mapping multiple times.
305
- */
306
-
307
-
308
- const modelFields = (0, _utils3.buildModelFields)({
309
- plugins: this.context.plugins,
310
- model
311
- });
312
- /**
313
- * Filter the read items via the code.
314
- * It will build the filters out of the where input and transform the values it is using.
315
- */
316
-
317
- const filteredItems = (0, _utils3.filterItems)({
318
- items,
319
- where: queryOptions.where,
320
- plugins: this.context.plugins,
321
- fields: modelFields
322
- });
323
- const totalCount = filteredItems.length;
324
- /**
325
- * Sorting is also done via the code.
326
- * It takes the sort input and sorts by it via the lodash sortBy method.
327
- */
328
-
329
- const sortedItems = (0, _utils3.sortEntryItems)({
330
- items: filteredItems,
331
- sort,
332
- fields: modelFields
333
- });
334
- const start = (0, _utils2.decodePaginationCursor)(after) || 0;
335
- const hasMoreItems = totalCount > start + limit;
336
- const end = limit > totalCount + start + limit ? undefined : start + limit;
337
- const slicedItems = sortedItems.slice(start, end);
338
- /**
339
- * Although we do not need a cursor here, we will use it as such to keep it standardized.
340
- * Number is simply encoded.
341
- */
342
-
343
- const cursor = totalCount > start + limit ? (0, _utils2.encodePaginationCursor)(start + limit) : null;
344
- return {
345
- hasMoreItems,
346
- totalCount,
347
- cursor,
348
- items: slicedItems
349
- };
350
- }
351
-
352
- async update(model, args) {
353
- const {
354
- originalEntry,
355
- entry,
356
- storageEntry
357
- } = args;
358
- const partitionKey = this.getPartitionKey(originalEntry.id);
359
- const items = [];
360
- /**
361
- * We need to:
362
- * - update the current entry
363
- * - update the latest entry if the current entry is the latest one
364
- */
365
-
366
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
367
- PK: partitionKey,
368
- SK: this.getSortKeyRevision(storageEntry.version),
369
- TYPE: TYPE_ENTRY,
370
- GSI1_PK: this.getGSIEntryPartitionKey(model),
371
- GSI1_SK: this.getGSISortKey(storageEntry)
372
- })));
373
- /**
374
- * We need the latest entry to update it as well if neccessary.
375
- */
376
-
377
- const latestStorageEntry = await this.getLatestRevisionByEntryId(model, entry.id);
378
-
379
- if (latestStorageEntry && latestStorageEntry.id === entry.id) {
380
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
381
- PK: partitionKey,
382
- SK: this.getSortKeyLatest(),
383
- TYPE: TYPE_ENTRY_LATEST,
384
- GSI1_PK: this.getGSILatestPartitionKey(model),
385
- GSI1_SK: this.getGSISortKey(entry)
386
- })));
387
- }
388
-
389
- try {
390
- await this._table.batchWrite(items);
391
- return storageEntry;
392
- } catch (ex) {
393
- throw new _error.default(ex.message || "Could not update entry.", ex.code || "UPDATE_ERROR", {
394
- error: ex,
395
- originalEntry,
396
- entry,
397
- latestStorageEntry
398
- });
399
- }
400
- }
401
-
402
- async publish(model, args) {
403
- const {
404
- entry,
405
- storageEntry
406
- } = args;
407
- const partitionKey = this.getPartitionKey(entry.id);
408
- /**
409
- * We need the latest and published entries to see if something needs to be updated along side the publishing one.
410
- */
411
-
412
- const latestStorageEntry = await this.getLatestRevisionByEntryId(model, entry.id);
413
- const publishedStorageEntry = await this.getPublishedRevisionByEntryId(model, entry.id);
414
- /**
415
- * We need to update:
416
- * - current entry revision sort key
417
- * - published sort key
418
- * - latest sort key - if entry updated is actually latest
419
- * - previous published entry to unpublished status - if any previously published entry
420
- */
421
-
422
- const items = [this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
423
- PK: partitionKey,
424
- SK: this.getSortKeyRevision(entry.version),
425
- TYPE: TYPE_ENTRY,
426
- GSI1_PK: this.getGSIEntryPartitionKey(model),
427
- GSI1_SK: this.getGSISortKey(entry)
428
- })), this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
429
- PK: partitionKey,
430
- SK: this.getSortKeyPublished(),
431
- TYPE: TYPE_ENTRY_PUBLISHED,
432
- GSI1_PK: this.getGSIPublishedPartitionKey(model),
433
- GSI1_SK: this.getGSISortKey(entry)
434
- }))];
435
-
436
- if (entry.id === latestStorageEntry.id) {
437
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
438
- PK: partitionKey,
439
- SK: this.getSortKeyLatest(),
440
- TYPE: TYPE_ENTRY_LATEST,
441
- GSI1_PK: this.getGSILatestPartitionKey(model),
442
- GSI1_SK: this.getGSISortKey(entry)
443
- })));
444
- }
445
-
446
- if (publishedStorageEntry) {
447
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, publishedStorageEntry), {}, {
448
- PK: partitionKey,
449
- SK: this.getSortKeyRevision(publishedStorageEntry.version),
450
- TYPE: TYPE_ENTRY,
451
- status: _types.CONTENT_ENTRY_STATUS.UNPUBLISHED,
452
- GSI1_PK: this.getGSIEntryPartitionKey(model),
453
- GSI1_SK: this.getGSISortKey(publishedStorageEntry)
454
- })));
455
- }
456
-
457
- try {
458
- await this._table.batchWrite(items);
459
-
460
- this._dataLoaders.clearAllEntryRevisions(model, entry);
461
-
462
- return entry;
463
- } catch (ex) {
464
- throw new _error.default(ex.message || "Could not execute the publishing batch.", ex.code || "PUBLISH_ERROR", {
465
- entry,
466
- latestStorageEntry,
467
- publishedStorageEntry
468
- });
469
- }
470
- }
471
-
472
- async unpublish(model, args) {
473
- const {
474
- entry,
475
- storageEntry
476
- } = args;
477
- const partitionKey = this.getPartitionKey(entry.id);
478
- /**
479
- * We need to:
480
- * - delete currently published entry
481
- * - update current entry revision with new data
482
- * - update latest entry status - if entry being unpublished is latest
483
- */
484
-
485
- const items = [this._entity.deleteBatch({
486
- PK: partitionKey,
487
- SK: this.getSortKeyPublished()
488
- }), this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
489
- PK: partitionKey,
490
- SK: this.getSortKeyRevision(entry.version),
491
- TYPE: TYPE_ENTRY,
492
- GSI1_PK: this.getGSIEntryPartitionKey(model),
493
- GSI1_SK: this.getGSISortKey(entry)
494
- }))];
495
- /**
496
- * We need the latest entry to see if something needs to be updated along side the unpublishing one.
497
- */
498
-
499
- const latestStorageEntry = await this.getLatestRevisionByEntryId(model, entry.id);
500
-
501
- if (entry.id === latestStorageEntry.id) {
502
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
503
- PK: partitionKey,
504
- SK: this.getSortKeyLatest(),
505
- TYPE: TYPE_ENTRY_LATEST,
506
- GSI1_PK: this.getGSILatestPartitionKey(model),
507
- GSI1_SK: this.getGSISortKey(entry)
508
- })));
509
- }
510
-
511
- try {
512
- await this._table.batchWrite(items);
513
- return storageEntry;
514
- } catch (ex) {
515
- throw new _error.default(ex.message || "Could not execute unpublish batch.", ex.code || "UNPUBLISH_ERROR", {
516
- entry,
517
- storageEntry
518
- });
519
- }
520
- }
521
-
522
- async requestChanges(model, args) {
523
- const {
524
- entry,
525
- storageEntry,
526
- originalEntry
527
- } = args;
528
- const partitionKey = this.getPartitionKey(entry.id);
529
- /**
530
- * We need to:
531
- * - update the existing entry
532
- * - update latest version - if existing entry is the latest version
533
- */
534
-
535
- const items = [this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
536
- PK: partitionKey,
537
- SK: this.getSortKeyRevision(entry.version),
538
- GSI1_PK: this.getGSIEntryPartitionKey(model),
539
- GSI1_SK: this.getGSISortKey(entry)
540
- }))];
541
- /**
542
- * We need the latest entry to see if something needs to be updated along side the request changes one.
543
- */
544
-
545
- const latestStorageEntry = await this.getLatestRevisionByEntryId(model, entry.id);
546
-
547
- if (latestStorageEntry.id === entry.id) {
548
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
549
- PK: partitionKey,
550
- SK: this.getSortKeyLatest(),
551
- TYPE: TYPE_ENTRY_LATEST,
552
- GSI1_PK: this.getGSILatestPartitionKey(model),
553
- GSI1_SK: this.getGSISortKey(entry)
554
- })));
555
- }
556
-
557
- try {
558
- await this._table.batchWrite(items);
559
- } catch (ex) {
560
- throw new _error.default(ex.message || "Could not execute the request changes batch.", ex.code || "REQUEST_CHANGES_ERROR", {
561
- entry,
562
- originalEntry
563
- });
564
- }
565
-
566
- return entry;
567
- }
568
-
569
- async requestReview(model, args) {
570
- const {
571
- entry,
572
- storageEntry,
573
- originalEntry
574
- } = args;
575
- const partitionKey = this.getPartitionKey(entry.id);
576
- /**
577
- * We need to:
578
- * - update existing entry
579
- * - update latest entry - if existing entry is the latest entry
580
- */
581
-
582
- const items = [this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
583
- PK: partitionKey,
584
- SK: this.getSortKeyRevision(entry.version),
585
- GSI1_PK: this.getGSIEntryPartitionKey(model),
586
- GSI1_SK: this.getGSISortKey(entry)
587
- }))];
588
- /**
589
- * We need the latest entry to see if something needs to be updated along side the request review one.
590
- */
591
-
592
- const latestStorageEntry = await this.getLatestRevisionByEntryId(model, entry.id);
593
-
594
- if (latestStorageEntry.id === entry.id) {
595
- items.push(this._entity.putBatch(_objectSpread(_objectSpread({}, storageEntry), {}, {
596
- PK: partitionKey,
597
- SK: this.getSortKeyLatest(),
598
- TYPE: TYPE_ENTRY_LATEST,
599
- GSI1_PK: this.getGSILatestPartitionKey(model),
600
- GSI1_SK: this.getGSISortKey(entry)
601
- })));
602
- }
603
-
604
- try {
605
- await this._table.batchWrite(items);
606
- return entry;
607
- } catch (ex) {
608
- throw new _error.default(ex.message || "Could not execute request review batch.", ex.code || "REQUEST_REVIEW_ERROR", {
609
- entry,
610
- storageEntry,
611
- originalEntry
612
- });
613
- }
614
- }
615
-
616
- async getAllRevisionsByIds(model, ids) {
617
- if (ids.length === 0) {
618
- return [];
619
- }
620
-
621
- try {
622
- return await this._dataLoaders.getAllEntryRevisions(model, ids);
623
- } catch (ex) {
624
- throw new _error.default(ex.message || "Could not read multiple entries.", ex.code || "GET_ALL_REVISIONS_BY_IDS_ERROR", {
625
- ids
626
- });
627
- }
628
- }
629
-
630
- async getByIds(model, ids) {
631
- if (ids.length === 0) {
632
- return [];
633
- }
634
-
635
- try {
636
- return await this._dataLoaders.getRevisionById(model, ids);
637
- } catch (ex) {
638
- throw new _error.default(ex.message || "Could not read multiple entries.", ex.code || "GET_BY_IDS_ERROR", {
639
- ids
640
- });
641
- }
642
- }
643
-
644
- async getPublishedByIds(model, ids) {
645
- if (ids.length === 0) {
646
- return [];
647
- }
648
-
649
- try {
650
- return await this._dataLoaders.getPublishedRevisionByEntryId(model, ids);
651
- } catch (ex) {
652
- throw new _error.default(ex.message || "Could not read multiple entries.", ex.code || "GET_BY_IDS_ERROR", {
653
- ids
654
- });
655
- }
656
- }
657
-
658
- async getLatestByIds(model, ids) {
659
- if (ids.length === 0) {
660
- return [];
661
- }
662
-
663
- try {
664
- return await this._dataLoaders.getLatestRevisionByEntryId(model, ids);
665
- } catch (ex) {
666
- throw new _error.default(ex.message || "Could not read multiple entries.", ex.code || "GET_BY_IDS_ERROR", {
667
- ids
668
- });
669
- }
670
- }
671
-
672
- async getRevisions(model, id) {
673
- try {
674
- return await this._dataLoaders.getAllEntryRevisions(model, [id]);
675
- } catch (ex) {
676
- throw new _error.default(ex.message || "Could not read multiple entries.", ex.code || "GET_ALL_REVISIONS_BY_IDS_ERROR", {
677
- id
678
- });
679
- }
680
- }
681
-
682
- async getRevisionById(model, id) {
683
- return this.getSingleDynamoDbItem({
684
- partitionKey: this.getPartitionKey(id),
685
- value: this.getSortKeyRevision(id)
686
- });
687
- }
688
-
689
- async getPublishedRevisionByEntryId(model, entryId) {
690
- return this.getSingleDynamoDbItem({
691
- partitionKey: this.getPartitionKey(entryId),
692
- value: this.getSortKeyPublished()
693
- });
694
- }
695
-
696
- async getLatestRevisionByEntryId(model, entryId) {
697
- return this.getSingleDynamoDbItem({
698
- partitionKey: this.getPartitionKey(entryId),
699
- value: this.getSortKeyLatest()
700
- });
701
- }
702
-
703
- async getPreviousRevision(model, entryId, version) {
704
- const entry = await this.getSingleDynamoDbItem({
705
- partitionKey: this.getPartitionKey(entryId),
706
- op: "lt",
707
- value: this.getSortKeyRevision(version),
708
- order: "DESC"
709
- });
710
-
711
- if (entry.TYPE !== TYPE_ENTRY) {
712
- return null;
713
- }
714
-
715
- return entry;
716
- }
717
-
718
- async getSingleDynamoDbItem(args) {
719
- const {
720
- partitionKey,
721
- op = "eq",
722
- value,
723
- order = "ASC"
724
- } = args;
725
- const queryOptions = {
726
- [op]: value,
727
- reverse: order === "DESC",
728
- limit: 1
729
- };
730
-
731
- try {
732
- const result = await this._entity.query(partitionKey, queryOptions);
733
-
734
- if (!result || Array.isArray(result.Items) === false) {
735
- throw new _error.default("Error when querying for content entries - no result.", "QUERY_ERROR", {
736
- partitionKey,
737
- queryOptions
738
- });
739
- }
740
-
741
- if (result.Items.length === 0) {
742
- return null;
743
- }
744
-
745
- return result.Items.shift();
746
- } catch (ex) {
747
- throw new _error.default(ex.message || "Could not read from the DynamoDB.", ex.code || "DDB_READ_ERROR", {
748
- partitionKey,
749
- queryOptions
750
- });
751
- }
752
- }
753
-
754
- getPartitionKey(id) {
755
- /**
756
- * If ID includes # it means it is composed of ID and VERSION.
757
- * We need ID only so extract it.
758
- */
759
- if (id.match("#") !== null) {
760
- id = id.split("#").shift();
761
- }
762
-
763
- return `${this.partitionKey}#${id}`;
764
- }
765
-
766
- get partitionKey() {
767
- return `${(0, _utils2.createBasePartitionKey)(this.context)}#CME`;
768
- }
769
-
770
- getGSIPartitionKey(type, model) {
771
- return `${this.partitionKey}#M#${model.modelId}#${type}`;
772
- }
773
-
774
- getGSIEntryPartitionKey(model) {
775
- return this.getGSIPartitionKey("A", model);
776
- }
777
-
778
- getGSILatestPartitionKey(model) {
779
- return this.getGSIPartitionKey("L", model);
780
- }
781
-
782
- getGSIPublishedPartitionKey(model) {
783
- return this.getGSIPartitionKey("P", model);
784
- }
785
-
786
- getGSISortKey(entry) {
787
- return entry.id;
788
- }
789
- /**
790
- * Gets a secondary key in form of REV#version from:
791
- * id#0003
792
- * 0003
793
- * 3
794
- */
795
-
796
-
797
- getSortKeyRevision(version) {
798
- if (typeof version === "string" && version.includes("#") === true) {
799
- version = version.split("#").pop();
800
- }
801
-
802
- return `REV#${(0, _utils.zeroPad)(version)}`;
803
- }
804
-
805
- getSortKeyLatest() {
806
- return "L";
807
- }
808
-
809
- getSortKeyPublished() {
810
- return "P";
811
- }
812
- /**
813
- * Method to build the query partition keys, always an array, and create the target index:
814
- * - if undefined then it is primary
815
- * - if populated then it is that given one (and partition keys are reflecting that)
816
- */
817
-
818
-
819
- createQueryOptions({
820
- where: originalWhere,
821
- model
822
- }) {
823
- const options = {
824
- filters: [],
825
- index: undefined
826
- };
827
- const where = (0, _lodash.default)(originalWhere);
828
- /**
829
- * if we have id or entry ID, we will query via the primary key
830
- * just add all the possible IDs to find
831
- */
832
-
833
- const queryPartitionKeys = [];
834
-
835
- if (where.id) {
836
- queryPartitionKeys.push(this.getPartitionKey(where.id));
837
- }
838
-
839
- if (where.entryId) {
840
- queryPartitionKeys.push(this.getPartitionKey(where.entryId));
841
- }
842
-
843
- if (where.id_in) {
844
- queryPartitionKeys.push(...where.id_in.map(id => this.getPartitionKey(id)));
845
- }
846
-
847
- if (where.entryId_in) {
848
- queryPartitionKeys.push(...where.entryId_in.map(id => this.getPartitionKey(id)));
849
- }
850
- /**
851
- * If we do not have any of the IDs, we will query via the GSI1_PK just depending on the entry type
852
- * At this point there will probably be a lot of results
853
- * but we will apply some basic dynamodb filters so we dont get much data from the db
854
- * NOTE: It is still going to get charged tho
855
- */
856
-
857
-
858
- if (queryPartitionKeys.length === 0) {
859
- options.index = GSI1_INDEX;
860
-
861
- if (where.published) {
862
- queryPartitionKeys.push(this.getGSIPartitionKey("P", model));
863
- } else if (where.latest) {
864
- queryPartitionKeys.push(this.getGSIPartitionKey("L", model));
865
- } else {
866
- queryPartitionKeys.push(this.getGSIPartitionKey("A", model));
867
- }
868
- }
869
- /**
870
- * If index is the primary one, we can filter records by type (latest, published or regular)
871
- * so we do not need to filter in the code
872
- */
873
-
874
-
875
- if (!options.index) {
876
- if (where.published) {
877
- options.eq = this.getSortKeyPublished();
878
- } else if (where.latest) {
879
- options.eq = this.getSortKeyLatest();
880
- } else {
881
- options.beginsWith = "REV#";
882
- }
883
- }
884
- /**
885
- * we remove all the used where conditions
886
- */
887
-
888
-
889
- delete where["id"];
890
- delete where["id_in"];
891
- delete where["entryId"];
892
- delete where["entryId_in"];
893
- delete where["published"];
894
- delete where["latest"];
895
- return {
896
- options,
897
- queryPartitionKeys,
898
- where
899
- };
900
- }
901
- /**
902
- * A method to query the database at the given partition key with the built query options.
903
- * Method runs in the loop until it reads everything it needs to.
904
- * We could impose the limit on the records read but there is no point since we MUST read everything to be able
905
- * to filter and sort the data.
906
- */
907
-
908
-
909
- async runQuery(args) {
910
- let previousResult = undefined;
911
- let results;
912
- const items = [];
913
-
914
- while (results = await this.query(previousResult, args)) {
915
- items.push(...results.Items);
916
- previousResult = results;
917
- }
918
-
919
- return items;
920
- }
921
-
922
- async query(previousResult, args) {
923
- const {
924
- partitionKey,
925
- options
926
- } = args;
927
- let result;
928
- /**
929
- * In case there is no previous result we must make a new query.
930
- * This is the first query on the given partition key.
931
- */
932
-
933
- if (!previousResult) {
934
- result = await this._entity.query(partitionKey, options);
935
- } else if (typeof previousResult.next === "function") {
936
- /**
937
- * In case we have a previous result and it has a next method, we run it.
938
- * In case result of the next method is false, it means it has nothing else to read
939
- * and we return a null to keep the query from repeating.
940
- */
941
- result = await previousResult.next();
942
-
943
- if (result === false) {
944
- return null;
945
- }
946
- } else {
947
- /**
948
- * This could probably never happen but keep it here just in case to break the query loop.
949
- * Basically, either previousResult does not exist or it exists and has a next method
950
- * and at that point a result returned will be null and loop should not start again.
951
- */
952
- return null;
953
- }
954
- /**
955
- * We expect the result to contain an Items array and if not, something went wrong, very wrong.
956
- */
957
-
958
-
959
- if (!result || !result.Items || !Array.isArray(result.Items)) {
960
- throw new _error.default("Error when querying for content entries - no result.", "QUERY_ERROR", {
961
- partitionKey,
962
- options
963
- });
964
- }
965
-
966
- return result;
967
- }
968
-
969
- }
970
-
971
- exports.CmsContentEntryDynamo = CmsContentEntryDynamo;
972
- //# sourceMappingURL=CmsContentEntryDynamo.js.map