@webiny/api-headless-cms 5.19.0-beta.1 → 5.19.0-beta.5

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.
@@ -7,6 +7,7 @@ interface Params {
7
7
  context: CmsContext;
8
8
  model: CmsModel;
9
9
  input: Record<string, ReferenceObject | ReferenceObject[]>;
10
+ validateEntries?: boolean;
10
11
  }
11
12
  export declare const referenceFieldsMapping: (params: Params) => Promise<Record<string, any>>;
12
13
  export {};
@@ -13,6 +13,8 @@ var _error = _interopRequireDefault(require("@webiny/error"));
13
13
 
14
14
  var _dotProp = _interopRequireDefault(require("dot-prop"));
15
15
 
16
+ var _utils = require("@webiny/utils");
17
+
16
18
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
17
19
 
18
20
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -116,11 +118,26 @@ const buildReferenceFieldPaths = params => {
116
118
  }, []);
117
119
  };
118
120
 
121
+ const getReferenceFieldValue = ref => {
122
+ if (!ref) {
123
+ return {
124
+ id: null,
125
+ modelId: null
126
+ };
127
+ }
128
+
129
+ return {
130
+ id: (ref.id || ref.entryId || "").trim() || null,
131
+ modelId: (ref.modelId || "").trim() || null
132
+ };
133
+ };
134
+
119
135
  const referenceFieldsMapping = async params => {
120
136
  const {
121
137
  context,
122
138
  model,
123
- input
139
+ input,
140
+ validateEntries = false
124
141
  } = params;
125
142
 
126
143
  let output = _objectSpread({}, input);
@@ -141,21 +158,26 @@ const referenceFieldsMapping = async params => {
141
158
  for (const path of referenceFieldPaths) {
142
159
  const ref = _dotProp.default.get(output, path);
143
160
 
144
- if (!ref || !ref.id || !ref.modelId) {
161
+ const {
162
+ id,
163
+ modelId
164
+ } = getReferenceFieldValue(ref);
165
+
166
+ if (!id || !modelId) {
145
167
  continue;
146
168
  }
147
169
 
148
- if (!referencesByModel[ref.modelId]) {
149
- referencesByModel[ref.modelId] = [];
170
+ if (!referencesByModel[modelId]) {
171
+ referencesByModel[modelId] = [];
150
172
  }
151
173
 
152
- referencesByModel[ref.modelId].push(ref.id);
174
+ referencesByModel[modelId].push(id);
153
175
 
154
- if (!pathsByReferenceId[ref.id]) {
155
- pathsByReferenceId[ref.id] = [];
176
+ if (!pathsByReferenceId[id]) {
177
+ pathsByReferenceId[id] = [];
156
178
  }
157
179
 
158
- pathsByReferenceId[ref.id].push(path);
180
+ pathsByReferenceId[id].push(path);
159
181
  }
160
182
  /**
161
183
  * Again, no point in going further.
@@ -197,7 +219,11 @@ const referenceFieldsMapping = async params => {
197
219
  const results = await Promise.all(promises);
198
220
  const records = results.reduce((collection, entries) => {
199
221
  for (const entry of entries) {
200
- collection[entry.id] = entry;
222
+ collection[entry.id] = {
223
+ id: entry.id,
224
+ entryId: entry.entryId,
225
+ modelId: entry.modelId
226
+ };
201
227
  }
202
228
 
203
229
  return collection;
@@ -209,15 +235,24 @@ const referenceFieldsMapping = async params => {
209
235
  for (const modelId in referencesByModel) {
210
236
  const entries = referencesByModel[modelId];
211
237
 
212
- for (const entry of entries) {
213
- if (records[entry]) {
238
+ for (const id of entries) {
239
+ if (records[id]) {
214
240
  continue;
241
+ } else if (validateEntries === true) {
242
+ throw new _error.default(`Missing referenced entry with id "${id}" in model "${modelId}".`, "ENTRY_NOT_FOUND", {
243
+ id,
244
+ model: modelId
245
+ });
215
246
  }
216
247
 
217
- throw new _error.default(`Missing referenced entry with id "${entry}" in model "${modelId}".`, "ENTRY_NOT_FOUND", {
218
- entry,
219
- model: modelId
220
- });
248
+ const {
249
+ id: entryId
250
+ } = (0, _utils.parseIdentifier)(id);
251
+ records[id] = {
252
+ id,
253
+ entryId,
254
+ modelId
255
+ };
221
256
  }
222
257
  }
223
258
  /**
@@ -230,10 +265,14 @@ const referenceFieldsMapping = async params => {
230
265
  const paths = pathsByReferenceId[id];
231
266
 
232
267
  if (!entry) {
233
- throw new _error.default("Missing entry in records.", "ENTRY_ERROR", {
234
- id,
235
- paths
236
- });
268
+ if (validateEntries === true) {
269
+ throw new _error.default("Missing entry in records.", "ENTRY_ERROR", {
270
+ id,
271
+ paths
272
+ });
273
+ }
274
+
275
+ continue;
237
276
  }
238
277
 
239
278
  for (const path of paths) {
@@ -380,7 +380,8 @@ const createContentEntryCrud = params => {
380
380
  const input = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
381
381
  context,
382
382
  model,
383
- input: initialInput
383
+ input: initialInput,
384
+ validateEntries: true
384
385
  });
385
386
  const identity = context.security.getIdentity();
386
387
  const locale = context.cms.getLocale();
@@ -480,7 +481,8 @@ const createContentEntryCrud = params => {
480
481
  const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
481
482
  context,
482
483
  model,
483
- input: initialValues
484
+ input: initialValues,
485
+ validateEntries: false
484
486
  });
485
487
  utils.checkOwnership(context, permission, originalEntry);
486
488
  const latestEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, latestStorageEntry);
@@ -578,7 +580,8 @@ const createContentEntryCrud = params => {
578
580
  const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
579
581
  context,
580
582
  model,
581
- input: initialValues
583
+ input: initialValues,
584
+ validateEntries: false
582
585
  });
583
586
  /**
584
587
  * We always send the full entry to the hooks and storage operations update.
@@ -624,6 +627,84 @@ const createContentEntryCrud = params => {
624
627
  });
625
628
  }
626
629
  },
630
+ republishEntry: async (model, id) => {
631
+ await checkEntryPermissions({
632
+ rwd: "w"
633
+ });
634
+ await utils.checkModelAccess(context, model);
635
+ /**
636
+ * Fetch the entry from the storage.
637
+ */
638
+
639
+ const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
640
+ id
641
+ });
642
+
643
+ if (!originalStorageEntry) {
644
+ throw new _handlerGraphql.NotFoundError(`Entry "${id}" was not found!`);
645
+ }
646
+
647
+ const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
648
+ /**
649
+ * We can only process published entries.
650
+ */
651
+
652
+ if (originalEntry.status !== "published") {
653
+ throw new _error.default("Entry with given ID is not published!", "NOT_PUBLISHED_ERROR", {
654
+ id,
655
+ original: originalEntry
656
+ });
657
+ }
658
+
659
+ const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
660
+ context,
661
+ model,
662
+ input: originalEntry.values,
663
+ validateEntries: false
664
+ });
665
+
666
+ const entry = _objectSpread(_objectSpread({}, originalEntry), {}, {
667
+ savedOn: new Date().toISOString(),
668
+ webinyVersion: context.WEBINY_VERSION,
669
+ values
670
+ });
671
+
672
+ const storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
673
+ /**
674
+ * First we need to update existing entry.
675
+ */
676
+
677
+ try {
678
+ await storageOperations.entries.update(model, {
679
+ originalEntry,
680
+ originalStorageEntry,
681
+ entry,
682
+ storageEntry,
683
+ input: {}
684
+ });
685
+ } catch (ex) {
686
+ throw new _error.default("Could not update existing entry with new data while re-publishing.", "REPUBLISH_UPDATE_ERROR", {
687
+ entry
688
+ });
689
+ }
690
+ /**
691
+ * Then we move onto publishing it again.
692
+ */
693
+
694
+
695
+ try {
696
+ return await storageOperations.entries.publish(model, {
697
+ originalEntry,
698
+ originalStorageEntry,
699
+ entry,
700
+ storageEntry
701
+ });
702
+ } catch (ex) {
703
+ throw new _error.default("Could not publish existing entry while re-publishing.", "REPUBLISH_PUBLISH_ERROR", {
704
+ entry
705
+ });
706
+ }
707
+ },
627
708
  deleteEntryRevision: async (model, revisionId) => {
628
709
  const permission = await checkEntryPermissions({
629
710
  rwd: "d"
@@ -35,7 +35,8 @@ const assignBeforeModelDelete = params => {
35
35
  const result = await storageOperations.entries.list(model, {
36
36
  where: {
37
37
  tenant: model.tenant,
38
- locale: model.locale
38
+ locale: model.locale,
39
+ latest: true
39
40
  },
40
41
  limit: 1
41
42
  });
@@ -31,6 +31,8 @@ var _resolveDelete = require("./resolvers/manage/resolveDelete");
31
31
 
32
32
  var _resolvePublish = require("./resolvers/manage/resolvePublish");
33
33
 
34
+ var _resolveRepublish = require("./resolvers/manage/resolveRepublish");
35
+
34
36
  var _resolveUnpublish = require("./resolvers/manage/resolveUnpublish");
35
37
 
36
38
  var _resolveCreateFrom = require("./resolvers/manage/resolveCreateFrom");
@@ -88,6 +90,9 @@ const createManageResolvers = ({
88
90
  [`publish${typeName}`]: (0, _resolvePublish.resolvePublish)({
89
91
  model
90
92
  }),
93
+ [`republish${typeName}`]: (0, _resolveRepublish.resolveRepublish)({
94
+ model
95
+ }),
91
96
  [`unpublish${typeName}`]: (0, _resolveUnpublish.resolveUnpublish)({
92
97
  model
93
98
  }),
@@ -139,6 +139,8 @@ const createManageSDL = ({
139
139
  delete${typeName}(revision: ID!): CmsDeleteResponse
140
140
 
141
141
  publish${typeName}(revision: ID!): ${mTypeName}Response
142
+
143
+ republish${typeName}(revision: ID!): ${mTypeName}Response
142
144
 
143
145
  unpublish${typeName}(revision: ID!): ${mTypeName}Response
144
146
 
@@ -0,0 +1,2 @@
1
+ import { CmsEntryResolverFactory as ResolverFactory } from "../../../../../types";
2
+ export declare const resolveRepublish: ResolverFactory;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.resolveRepublish = void 0;
7
+
8
+ var _responses = require("@webiny/handler-graphql/responses");
9
+
10
+ const resolveRepublish = ({
11
+ model
12
+ }) => async (_, args, context) => {
13
+ try {
14
+ const entry = await context.cms.republishEntry(model, args.revision);
15
+ return new _responses.Response(entry);
16
+ } catch (e) {
17
+ return new _responses.ErrorResponse(e);
18
+ }
19
+ };
20
+
21
+ exports.resolveRepublish = resolveRepublish;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-headless-cms",
3
- "version": "5.19.0-beta.1",
3
+ "version": "5.19.0-beta.5",
4
4
  "main": "index.js",
5
5
  "keywords": [
6
6
  "cms:base"
@@ -21,23 +21,23 @@
21
21
  "@babel/runtime": "7.16.3",
22
22
  "@commodo/fields": "1.1.2-beta.20",
23
23
  "@graphql-tools/schema": "7.1.5",
24
- "@webiny/api-file-manager": "5.19.0-beta.1",
25
- "@webiny/api-i18n": "5.19.0-beta.1",
26
- "@webiny/api-i18n-content": "5.19.0-beta.1",
27
- "@webiny/api-i18n-ddb": "5.19.0-beta.1",
28
- "@webiny/api-security": "5.19.0-beta.1",
29
- "@webiny/api-tenancy": "5.19.0-beta.1",
30
- "@webiny/api-upgrade": "5.19.0-beta.1",
31
- "@webiny/error": "5.19.0-beta.1",
32
- "@webiny/handler": "5.19.0-beta.1",
33
- "@webiny/handler-aws": "5.19.0-beta.1",
34
- "@webiny/handler-db": "5.19.0-beta.1",
35
- "@webiny/handler-graphql": "5.19.0-beta.1",
36
- "@webiny/handler-http": "5.19.0-beta.1",
37
- "@webiny/plugins": "5.19.0-beta.1",
38
- "@webiny/pubsub": "5.19.0-beta.1",
39
- "@webiny/utils": "5.19.0-beta.1",
40
- "@webiny/validation": "5.19.0-beta.1",
24
+ "@webiny/api-file-manager": "5.19.0-beta.5",
25
+ "@webiny/api-i18n": "5.19.0-beta.5",
26
+ "@webiny/api-i18n-content": "5.19.0-beta.5",
27
+ "@webiny/api-i18n-ddb": "5.19.0-beta.5",
28
+ "@webiny/api-security": "5.19.0-beta.5",
29
+ "@webiny/api-tenancy": "5.19.0-beta.5",
30
+ "@webiny/api-upgrade": "5.19.0-beta.5",
31
+ "@webiny/error": "5.19.0-beta.5",
32
+ "@webiny/handler": "5.19.0-beta.5",
33
+ "@webiny/handler-aws": "5.19.0-beta.5",
34
+ "@webiny/handler-db": "5.19.0-beta.5",
35
+ "@webiny/handler-graphql": "5.19.0-beta.5",
36
+ "@webiny/handler-http": "5.19.0-beta.5",
37
+ "@webiny/plugins": "5.19.0-beta.5",
38
+ "@webiny/pubsub": "5.19.0-beta.5",
39
+ "@webiny/utils": "5.19.0-beta.5",
40
+ "@webiny/validation": "5.19.0-beta.5",
41
41
  "boolean": "3.1.4",
42
42
  "commodo-fields-object": "1.0.6",
43
43
  "dataloader": "2.0.0",
@@ -54,10 +54,10 @@
54
54
  "@babel/core": "^7.5.5",
55
55
  "@babel/preset-env": "^7.5.5",
56
56
  "@babel/preset-flow": "^7.0.0",
57
- "@webiny/api-security-so-ddb": "^5.19.0-beta.1",
58
- "@webiny/api-tenancy-so-ddb": "^5.19.0-beta.1",
59
- "@webiny/cli": "^5.19.0-beta.1",
60
- "@webiny/project-utils": "^5.19.0-beta.1",
57
+ "@webiny/api-security-so-ddb": "^5.19.0-beta.5",
58
+ "@webiny/api-tenancy-so-ddb": "^5.19.0-beta.5",
59
+ "@webiny/cli": "^5.19.0-beta.5",
60
+ "@webiny/project-utils": "^5.19.0-beta.5",
61
61
  "apollo-graphql": "^0.4.1",
62
62
  "get-yarn-workspaces": "^1.0.2",
63
63
  "graphql": "^14.6.0",
@@ -77,5 +77,5 @@
77
77
  "build": "yarn webiny run build",
78
78
  "watch": "yarn webiny run watch"
79
79
  },
80
- "gitHead": "dd406fbad0620ecce47063e9afbff40c502c3844"
80
+ "gitHead": "839188911bbaee4a596724c729c0a78f681fa614"
81
81
  }
@@ -162,17 +162,34 @@ const createSystemCrud = params => {
162
162
 
163
163
  const upgradePlugins = context.plugins.byType("api-upgrade").filter(pl => pl.app === "headless-cms");
164
164
  const installedAppVersion = await this.getSystemVersion();
165
- const plugin = (0, _apiUpgrade.getApplicablePlugin)({
166
- deployedVersion: context.WEBINY_VERSION,
167
- installedAppVersion,
168
- upgradePlugins,
169
- upgradeToVersion: version
170
- });
171
- await plugin.apply(context);
165
+ let plugin;
166
+
167
+ try {
168
+ plugin = (0, _apiUpgrade.getApplicablePlugin)({
169
+ deployedVersion: context.WEBINY_VERSION,
170
+ installedAppVersion,
171
+ upgradePlugins,
172
+ upgradeToVersion: version
173
+ });
174
+ } catch (ex) {
175
+ /**
176
+ * We just let the error disappear if is UPGRADE_NOT_AVAILABLE code
177
+ * and rethrow if is not.
178
+ * This is because we want upgrade to pass if there is no plugin available.
179
+ */
180
+ if (ex.code !== _apiUpgrade.ErrorCode.UPGRADE_NOT_AVAILABLE) {
181
+ throw ex;
182
+ }
183
+ }
184
+
185
+ if (plugin) {
186
+ await plugin.apply(context);
187
+ }
172
188
  /**
173
189
  * Store new app version.
174
190
  */
175
191
 
192
+
176
193
  await setVersion(version);
177
194
  return true;
178
195
  }
package/types.d.ts CHANGED
@@ -1525,6 +1525,11 @@ export interface CmsEntryContext {
1525
1525
  * Update existing entry.
1526
1526
  */
1527
1527
  updateEntry: (model: CmsModel, id: string, data?: Record<string, any>) => Promise<CmsEntry>;
1528
+ /**
1529
+ * Method that republishes entry with given identifier.
1530
+ * @internal
1531
+ */
1532
+ republishEntry: (model: CmsModel, id: string) => Promise<CmsEntry>;
1528
1533
  /**
1529
1534
  * Delete only a certain revision of the entry.
1530
1535
  */