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