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