@atlaskit/editor-synced-block-provider 2.12.1 → 2.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/clients/block-service/blockService.js +6 -5
- package/dist/cjs/clients/confluence/contentProperty.js +4 -3
- package/dist/cjs/clients/confluence/sourceInfo.js +2 -1
- package/dist/cjs/common/types.js +5 -0
- package/dist/cjs/providers/block-service/blockServiceAPI.js +81 -37
- package/dist/cjs/providers/confluence/confluenceContentAPI.js +80 -42
- package/dist/cjs/providers/syncBlockProvider.js +13 -2
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +4 -6
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +10 -12
- package/dist/cjs/utils/resolveSyncBlockInstance.js +8 -4
- package/dist/cjs/utils/retry.js +66 -0
- package/dist/cjs/utils/utils.js +1 -10
- package/dist/es2019/clients/block-service/blockService.js +6 -5
- package/dist/es2019/clients/confluence/contentProperty.js +4 -3
- package/dist/es2019/clients/confluence/sourceInfo.js +2 -1
- package/dist/es2019/common/types.js +5 -0
- package/dist/es2019/providers/block-service/blockServiceAPI.js +43 -15
- package/dist/es2019/providers/confluence/confluenceContentAPI.js +35 -10
- package/dist/es2019/providers/syncBlockProvider.js +5 -0
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +4 -6
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +11 -13
- package/dist/es2019/utils/resolveSyncBlockInstance.js +8 -4
- package/dist/es2019/utils/retry.js +26 -0
- package/dist/es2019/utils/utils.js +0 -9
- package/dist/esm/clients/block-service/blockService.js +6 -5
- package/dist/esm/clients/confluence/contentProperty.js +4 -3
- package/dist/esm/clients/confluence/sourceInfo.js +2 -1
- package/dist/esm/common/types.js +5 -0
- package/dist/esm/providers/block-service/blockServiceAPI.js +81 -37
- package/dist/esm/providers/confluence/confluenceContentAPI.js +80 -42
- package/dist/esm/providers/syncBlockProvider.js +13 -2
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +4 -6
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +11 -13
- package/dist/esm/utils/resolveSyncBlockInstance.js +8 -4
- package/dist/esm/utils/retry.js +60 -0
- package/dist/esm/utils/utils.js +0 -9
- package/dist/types/common/types.d.ts +4 -0
- package/dist/types/providers/block-service/blockServiceAPI.d.ts +1 -0
- package/dist/types/providers/confluence/confluenceContentAPI.d.ts +1 -0
- package/dist/types/providers/syncBlockProvider.d.ts +1 -0
- package/dist/types/providers/types.d.ts +2 -0
- package/dist/types/utils/retry.d.ts +1 -0
- package/dist/types/utils/utils.d.ts +0 -1
- package/dist/types-ts4.5/common/types.d.ts +4 -0
- package/dist/types-ts4.5/providers/block-service/blockServiceAPI.d.ts +1 -0
- package/dist/types-ts4.5/providers/confluence/confluenceContentAPI.d.ts +1 -0
- package/dist/types-ts4.5/providers/syncBlockProvider.d.ts +1 -0
- package/dist/types-ts4.5/providers/types.d.ts +2 -0
- package/dist/types-ts4.5/utils/retry.d.ts +1 -0
- package/dist/types-ts4.5/utils/utils.d.ts +0 -1
- package/package.json +2 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.fetchWithRetry = void 0;
|
|
8
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
|
+
var parseRetryAfter = function parseRetryAfter(retryAfter) {
|
|
11
|
+
var newDelay;
|
|
12
|
+
|
|
13
|
+
// retryAfter can either be in ms or HTTP date
|
|
14
|
+
var parsedRetryAfter = parseInt(retryAfter);
|
|
15
|
+
if (!isNaN(parsedRetryAfter)) {
|
|
16
|
+
newDelay = parsedRetryAfter * 1000;
|
|
17
|
+
} else {
|
|
18
|
+
var retryDate = new Date(retryAfter);
|
|
19
|
+
var delayFromDate = retryDate.getTime() - Date.now();
|
|
20
|
+
if (delayFromDate > 0) {
|
|
21
|
+
newDelay = delayFromDate;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return newDelay;
|
|
25
|
+
};
|
|
26
|
+
var _fetchWithRetry = exports.fetchWithRetry = /*#__PURE__*/function () {
|
|
27
|
+
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(url, options) {
|
|
28
|
+
var retriesRemaining,
|
|
29
|
+
delay,
|
|
30
|
+
response,
|
|
31
|
+
shouldRetry,
|
|
32
|
+
retryAfter,
|
|
33
|
+
_args = arguments;
|
|
34
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
35
|
+
while (1) switch (_context.prev = _context.next) {
|
|
36
|
+
case 0:
|
|
37
|
+
retriesRemaining = _args.length > 2 && _args[2] !== undefined ? _args[2] : 3;
|
|
38
|
+
delay = _args.length > 3 && _args[3] !== undefined ? _args[3] : 1000;
|
|
39
|
+
_context.next = 4;
|
|
40
|
+
return fetch(url, options);
|
|
41
|
+
case 4:
|
|
42
|
+
response = _context.sent;
|
|
43
|
+
shouldRetry = !response.ok && response.status === 429 && retriesRemaining > 1;
|
|
44
|
+
if (shouldRetry) {
|
|
45
|
+
_context.next = 8;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
return _context.abrupt("return", response);
|
|
49
|
+
case 8:
|
|
50
|
+
retryAfter = response.headers.get('Retry-After');
|
|
51
|
+
_context.next = 11;
|
|
52
|
+
return new Promise(function (resolve) {
|
|
53
|
+
return setTimeout(resolve, retryAfter ? parseRetryAfter(retryAfter) : delay);
|
|
54
|
+
});
|
|
55
|
+
case 11:
|
|
56
|
+
return _context.abrupt("return", _fetchWithRetry(url, options, retriesRemaining - 1, delay * 2));
|
|
57
|
+
case 12:
|
|
58
|
+
case "end":
|
|
59
|
+
return _context.stop();
|
|
60
|
+
}
|
|
61
|
+
}, _callee);
|
|
62
|
+
}));
|
|
63
|
+
return function fetchWithRetry(_x, _x2) {
|
|
64
|
+
return _ref.apply(this, arguments);
|
|
65
|
+
};
|
|
66
|
+
}();
|
package/dist/cjs/utils/utils.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.createSyncBlockNode = exports.
|
|
6
|
+
exports.createSyncBlockNode = exports.convertSyncBlockPMNodeToSyncBlockData = exports.convertSyncBlockJSONNodeToSyncBlockNode = exports.convertPMNodesToSyncBlockNodes = exports.convertPMNodeToSyncBlockNode = void 0;
|
|
7
7
|
var convertSyncBlockPMNodeToSyncBlockData = exports.convertSyncBlockPMNodeToSyncBlockData = function convertSyncBlockPMNodeToSyncBlockData(node) {
|
|
8
8
|
return {
|
|
9
9
|
blockInstanceId: node.attrs.localId,
|
|
@@ -20,15 +20,6 @@ var createSyncBlockNode = exports.createSyncBlockNode = function createSyncBlock
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
|
-
var createBodiedSyncBlockNode = exports.createBodiedSyncBlockNode = function createBodiedSyncBlockNode(localId, resourceId) {
|
|
24
|
-
return {
|
|
25
|
-
type: 'bodiedSyncBlock',
|
|
26
|
-
attrs: {
|
|
27
|
-
localId: localId,
|
|
28
|
-
resourceId: resourceId
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
23
|
var convertSyncBlockJSONNodeToSyncBlockNode = exports.convertSyncBlockJSONNodeToSyncBlockNode = function convertSyncBlockJSONNodeToSyncBlockNode(node) {
|
|
33
24
|
if (node.type !== 'syncBlock' || !node.attrs || !('localId' in node.attrs) || !('resourceId' in node.attrs) || typeof node.attrs.localId !== 'string' || typeof node.attrs.resourceId !== 'string') {
|
|
34
25
|
return undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fetchWithRetry } from '../../utils/retry';
|
|
1
2
|
export const isBlockContentResponse = response => {
|
|
2
3
|
const content = response.content;
|
|
3
4
|
return typeof content === 'string';
|
|
@@ -46,7 +47,7 @@ export const isBlockContentResponse = response => {
|
|
|
46
47
|
* Check https://block-service.dev.atl-paas.net/ for latest API documentation.
|
|
47
48
|
*/
|
|
48
49
|
export const getReferenceSyncedBlocks = async documentAri => {
|
|
49
|
-
const response = await
|
|
50
|
+
const response = await fetchWithRetry(`${BLOCK_SERVICE_API_URL}/block/document/reference/${encodeURIComponent(documentAri)}`, {
|
|
50
51
|
method: 'GET',
|
|
51
52
|
headers: COMMON_HEADERS
|
|
52
53
|
});
|
|
@@ -69,7 +70,7 @@ export class BlockError extends Error {
|
|
|
69
70
|
export const getSyncedBlockContent = async ({
|
|
70
71
|
blockAri
|
|
71
72
|
}) => {
|
|
72
|
-
const response = await
|
|
73
|
+
const response = await fetchWithRetry(`${BLOCK_SERVICE_API_URL}/block/${encodeURIComponent(blockAri)}`, {
|
|
73
74
|
method: 'GET',
|
|
74
75
|
headers: COMMON_HEADERS
|
|
75
76
|
});
|
|
@@ -81,7 +82,7 @@ export const getSyncedBlockContent = async ({
|
|
|
81
82
|
export const deleteSyncedBlock = async ({
|
|
82
83
|
blockAri
|
|
83
84
|
}) => {
|
|
84
|
-
const response = await
|
|
85
|
+
const response = await fetchWithRetry(`${BLOCK_SERVICE_API_URL}/block/${encodeURIComponent(blockAri)}`, {
|
|
85
86
|
method: 'DELETE',
|
|
86
87
|
headers: COMMON_HEADERS
|
|
87
88
|
});
|
|
@@ -93,7 +94,7 @@ export const updateSyncedBlock = async ({
|
|
|
93
94
|
blockAri,
|
|
94
95
|
content
|
|
95
96
|
}) => {
|
|
96
|
-
const response = await
|
|
97
|
+
const response = await fetchWithRetry(`${BLOCK_SERVICE_API_URL}/block/${encodeURIComponent(blockAri)}`, {
|
|
97
98
|
method: 'PUT',
|
|
98
99
|
headers: COMMON_HEADERS,
|
|
99
100
|
body: JSON.stringify({
|
|
@@ -111,7 +112,7 @@ export const createSyncedBlock = async ({
|
|
|
111
112
|
product,
|
|
112
113
|
content
|
|
113
114
|
}) => {
|
|
114
|
-
const response = await
|
|
115
|
+
const response = await fetchWithRetry(`${BLOCK_SERVICE_API_URL}/block`, {
|
|
115
116
|
method: 'POST',
|
|
116
117
|
headers: COMMON_HEADERS,
|
|
117
118
|
body: JSON.stringify({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fetchWithRetry } from '../../utils/retry';
|
|
1
2
|
import { getConfluencePageAri } from './ari';
|
|
2
3
|
import { isBlogPageType } from './utils';
|
|
3
4
|
const COMMON_HEADERS = {
|
|
@@ -151,7 +152,7 @@ export const getContentProperty = async ({
|
|
|
151
152
|
keys: [key]
|
|
152
153
|
}
|
|
153
154
|
};
|
|
154
|
-
const response = await
|
|
155
|
+
const response = await fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
155
156
|
method: 'POST',
|
|
156
157
|
headers: {
|
|
157
158
|
...COMMON_HEADERS,
|
|
@@ -237,7 +238,7 @@ export const createContentProperty = async ({
|
|
|
237
238
|
}
|
|
238
239
|
}
|
|
239
240
|
};
|
|
240
|
-
const response = await
|
|
241
|
+
const response = await fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
241
242
|
method: 'POST',
|
|
242
243
|
headers: {
|
|
243
244
|
...COMMON_HEADERS,
|
|
@@ -272,7 +273,7 @@ export const deleteContentProperty = async ({
|
|
|
272
273
|
}
|
|
273
274
|
}
|
|
274
275
|
};
|
|
275
|
-
const response = await
|
|
276
|
+
const response = await fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
276
277
|
method: 'POST',
|
|
277
278
|
headers: {
|
|
278
279
|
...COMMON_HEADERS,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
4
4
|
import { getSourceInfoErrorPayload } from '../../utils/errorHandling';
|
|
5
|
+
import { fetchWithRetry } from '../../utils/retry';
|
|
5
6
|
import { getPageIdAndTypeFromConfluencePageAri } from './ari';
|
|
6
7
|
import { isBlogPageType } from './utils';
|
|
7
8
|
const COMMON_HEADERS = {
|
|
@@ -41,7 +42,7 @@ const getConfluenceSourceInfo = async ari => {
|
|
|
41
42
|
id: ari
|
|
42
43
|
}
|
|
43
44
|
};
|
|
44
|
-
const response = await
|
|
45
|
+
const response = await fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
45
46
|
method: 'POST',
|
|
46
47
|
headers: {
|
|
47
48
|
...COMMON_HEADERS,
|
|
@@ -2,6 +2,11 @@ export let SyncBlockError = /*#__PURE__*/function (SyncBlockError) {
|
|
|
2
2
|
SyncBlockError["Errored"] = "errored";
|
|
3
3
|
SyncBlockError["NotFound"] = "not_found";
|
|
4
4
|
SyncBlockError["Forbidden"] = "forbidden";
|
|
5
|
+
SyncBlockError["InvalidRequest"] = "invalid_request";
|
|
6
|
+
SyncBlockError["RateLimited"] = "rate_limited";
|
|
7
|
+
SyncBlockError["Conflict"] = "conflict";
|
|
8
|
+
// attempt to create block that already exists
|
|
9
|
+
SyncBlockError["ServerError"] = "server_error";
|
|
5
10
|
SyncBlockError["InvalidContent"] = "invalid_content"; // content is not a valid JSON
|
|
6
11
|
return SyncBlockError;
|
|
7
12
|
}({});
|
|
@@ -5,10 +5,21 @@ import { SyncBlockError } from '../../common/types';
|
|
|
5
5
|
import { stringifyError } from '../../utils/errorHandling';
|
|
6
6
|
const mapBlockError = error => {
|
|
7
7
|
switch (error.status) {
|
|
8
|
+
case 400:
|
|
9
|
+
case 401:
|
|
10
|
+
return SyncBlockError.InvalidRequest;
|
|
8
11
|
case 403:
|
|
9
12
|
return SyncBlockError.Forbidden;
|
|
10
13
|
case 404:
|
|
11
14
|
return SyncBlockError.NotFound;
|
|
15
|
+
case 409:
|
|
16
|
+
return SyncBlockError.Conflict;
|
|
17
|
+
case 429:
|
|
18
|
+
return SyncBlockError.RateLimited;
|
|
19
|
+
case 500:
|
|
20
|
+
case 503:
|
|
21
|
+
case 504:
|
|
22
|
+
return SyncBlockError.ServerError;
|
|
12
23
|
}
|
|
13
24
|
return SyncBlockError.Errored;
|
|
14
25
|
};
|
|
@@ -138,21 +149,38 @@ class BlockServiceADFWriteProvider {
|
|
|
138
149
|
};
|
|
139
150
|
} catch (error) {
|
|
140
151
|
if (error instanceof BlockError) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
return {
|
|
153
|
+
error: mapBlockError(error),
|
|
154
|
+
resourceId
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
error: stringifyError(error),
|
|
159
|
+
resourceId
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async createData(data) {
|
|
164
|
+
const {
|
|
165
|
+
resourceId
|
|
166
|
+
} = data;
|
|
167
|
+
try {
|
|
168
|
+
await createSyncedBlock({
|
|
169
|
+
blockAri: resourceId,
|
|
170
|
+
blockInstanceId: data.blockInstanceId,
|
|
171
|
+
sourceAri: this.sourceAri,
|
|
172
|
+
product: this.product,
|
|
173
|
+
content: JSON.stringify(data.content)
|
|
174
|
+
});
|
|
175
|
+
return {
|
|
176
|
+
resourceId
|
|
177
|
+
};
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (error instanceof BlockError) {
|
|
180
|
+
return {
|
|
181
|
+
error: mapBlockError(error),
|
|
182
|
+
resourceId
|
|
183
|
+
};
|
|
156
184
|
}
|
|
157
185
|
return {
|
|
158
186
|
error: stringifyError(error),
|
|
@@ -182,16 +182,6 @@ class ConfluenceADFWriteProvider {
|
|
|
182
182
|
return {
|
|
183
183
|
resourceId
|
|
184
184
|
};
|
|
185
|
-
} else if (!updateResult) {
|
|
186
|
-
return this.createNewContentProperty(pageId, key, syncBlockDataWithSourceDocumentAri, pageType).then(() => {
|
|
187
|
-
return {
|
|
188
|
-
resourceId
|
|
189
|
-
};
|
|
190
|
-
}, error => {
|
|
191
|
-
return {
|
|
192
|
-
error
|
|
193
|
-
};
|
|
194
|
-
});
|
|
195
185
|
} else {
|
|
196
186
|
return {
|
|
197
187
|
error: `Failed to update ${pageType} content property`
|
|
@@ -203,6 +193,41 @@ class ConfluenceADFWriteProvider {
|
|
|
203
193
|
};
|
|
204
194
|
}
|
|
205
195
|
}
|
|
196
|
+
async createData(syncBlockData) {
|
|
197
|
+
let match;
|
|
198
|
+
const {
|
|
199
|
+
resourceId
|
|
200
|
+
} = syncBlockData;
|
|
201
|
+
try {
|
|
202
|
+
match = getPageIdAndTypeFromConfluencePageAri(resourceId);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
return {
|
|
205
|
+
error: stringifyError(error)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const {
|
|
209
|
+
id: pageId,
|
|
210
|
+
type: pageType
|
|
211
|
+
} = match;
|
|
212
|
+
try {
|
|
213
|
+
const localId = getLocalIdFromConfluencePageAri(resourceId);
|
|
214
|
+
const key = getContentPropertyKey(this.config.contentPropertyKey, localId);
|
|
215
|
+
const sourceAri = getConfluencePageAri(pageId, this.config.cloudId, pageType);
|
|
216
|
+
const syncBlockDataWithSourceDocumentAri = {
|
|
217
|
+
...syncBlockData,
|
|
218
|
+
product: 'confluence-page',
|
|
219
|
+
sourceAri
|
|
220
|
+
};
|
|
221
|
+
await this.createNewContentProperty(pageId, key, syncBlockDataWithSourceDocumentAri, pageType);
|
|
222
|
+
return {
|
|
223
|
+
resourceId
|
|
224
|
+
};
|
|
225
|
+
} catch (error) {
|
|
226
|
+
return Promise.resolve({
|
|
227
|
+
error: stringifyError(error)
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
206
231
|
async deleteData(resourceId) {
|
|
207
232
|
let deletePayload, deleteResult, match;
|
|
208
233
|
try {
|
|
@@ -98,6 +98,11 @@ export class SyncBlockProvider extends SyncBlockDataProvider {
|
|
|
98
98
|
}
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
|
+
createNodeData(data) {
|
|
102
|
+
return this.writeProvider.createData(data).then(result => result, error => ({
|
|
103
|
+
error
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
101
106
|
|
|
102
107
|
/**
|
|
103
108
|
* Delete the data from the write provider
|
|
@@ -139,17 +139,15 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
139
139
|
(_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, fetchErrorPayload(syncBlockInstance.error || 'Returned sync block instance does not have resource id'));
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
142
|
+
const existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
|
|
143
|
+
const resolvedSyncBlockInstance = existingSyncBlock ? resolveSyncBlockInstance(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
|
|
144
|
+
this.updateCache(resolvedSyncBlockInstance);
|
|
145
|
+
resolvedData.push(resolvedSyncBlockInstance);
|
|
142
146
|
if (syncBlockInstance.error) {
|
|
143
147
|
var _this$fireAnalyticsEv6;
|
|
144
148
|
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, fetchErrorPayload(syncBlockInstance.error));
|
|
145
|
-
this.updateCache(syncBlockInstance);
|
|
146
|
-
resolvedData.push(syncBlockInstance);
|
|
147
149
|
return;
|
|
148
150
|
}
|
|
149
|
-
const existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
|
|
150
|
-
const resolvedSyncBlockInstance = existingSyncBlock ? resolveSyncBlockInstance(existingSyncBlock, syncBlockInstance) : syncBlockInstance;
|
|
151
|
-
this.updateCache(resolvedSyncBlockInstance);
|
|
152
|
-
resolvedData.push(resolvedSyncBlockInstance);
|
|
153
151
|
this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
154
152
|
});
|
|
155
153
|
return [...resolvedData, ...blocksWithNotFoundError];
|
|
@@ -3,7 +3,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
3
3
|
import uuid from 'uuid';
|
|
4
4
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
5
5
|
import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload } from '../utils/errorHandling';
|
|
6
|
-
import { convertSyncBlockPMNodeToSyncBlockData
|
|
6
|
+
import { convertSyncBlockPMNodeToSyncBlockData } from '../utils/utils';
|
|
7
7
|
// A store manager responsible for the lifecycle and state management of source sync blocks in an editor instance.
|
|
8
8
|
// Designed to manage local in-memory state and synchronize with an external data provider.
|
|
9
9
|
// Supports create, flush, and delete operations for source sync blocks.
|
|
@@ -172,21 +172,19 @@ export class SourceSyncBlockStoreManager {
|
|
|
172
172
|
resourceId,
|
|
173
173
|
localId: blockInstanceId
|
|
174
174
|
} = attrs;
|
|
175
|
-
this.dataProvider.
|
|
175
|
+
this.dataProvider.createNodeData({
|
|
176
176
|
content: [],
|
|
177
177
|
blockInstanceId,
|
|
178
178
|
resourceId: resourceId
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
});
|
|
179
|
+
}).then(result => {
|
|
180
|
+
const resourceId = result.resourceId;
|
|
181
|
+
if (resourceId) {
|
|
182
|
+
this.commitPendingCreation(true);
|
|
183
|
+
} else {
|
|
184
|
+
var _this$fireAnalyticsEv4;
|
|
185
|
+
this.commitPendingCreation(false);
|
|
186
|
+
(_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 ? void 0 : _this$fireAnalyticsEv4.call(this, createErrorPayload(result.error || 'Failed to create bodied sync block'));
|
|
187
|
+
}
|
|
190
188
|
}).catch(error => {
|
|
191
189
|
var _this$fireAnalyticsEv5;
|
|
192
190
|
this.commitPendingCreation(false);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SyncBlockError } from '../common/types';
|
|
1
2
|
/**
|
|
2
3
|
* Merges two SyncBlockInstance objects,
|
|
3
4
|
* currently it only preserves the sourceURL from the old result,
|
|
@@ -10,13 +11,16 @@
|
|
|
10
11
|
*/
|
|
11
12
|
export const resolveSyncBlockInstance = (oldResult, newResult) => {
|
|
12
13
|
var _newResult$data, _oldResult$data, _newResult$data2, _oldResult$data2;
|
|
13
|
-
// if the old result has no data, we
|
|
14
|
+
// if the old result has no data, we simply return the new result
|
|
14
15
|
if (!oldResult.data) {
|
|
15
16
|
return newResult;
|
|
16
17
|
} else if (!newResult.data) {
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// return the old result if there was an error, e.g. network error, but not if not found or forbidden
|
|
19
|
+
if (newResult.error === SyncBlockError.NotFound || newResult.error === SyncBlockError.Forbidden) {
|
|
20
|
+
return newResult;
|
|
21
|
+
} else {
|
|
22
|
+
return oldResult;
|
|
23
|
+
}
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
// otherwise, we merge the two results, preserving the sourceURL and sourceTitle from the old result if it exists
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const parseRetryAfter = retryAfter => {
|
|
2
|
+
let newDelay;
|
|
3
|
+
|
|
4
|
+
// retryAfter can either be in ms or HTTP date
|
|
5
|
+
const parsedRetryAfter = parseInt(retryAfter);
|
|
6
|
+
if (!isNaN(parsedRetryAfter)) {
|
|
7
|
+
newDelay = parsedRetryAfter * 1000;
|
|
8
|
+
} else {
|
|
9
|
+
const retryDate = new Date(retryAfter);
|
|
10
|
+
const delayFromDate = retryDate.getTime() - Date.now();
|
|
11
|
+
if (delayFromDate > 0) {
|
|
12
|
+
newDelay = delayFromDate;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return newDelay;
|
|
16
|
+
};
|
|
17
|
+
export const fetchWithRetry = async (url, options, retriesRemaining = 3, delay = 1000) => {
|
|
18
|
+
const response = await fetch(url, options);
|
|
19
|
+
const shouldRetry = !response.ok && response.status === 429 && retriesRemaining > 1;
|
|
20
|
+
if (!shouldRetry) {
|
|
21
|
+
return response;
|
|
22
|
+
}
|
|
23
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
24
|
+
await new Promise(resolve => setTimeout(resolve, retryAfter ? parseRetryAfter(retryAfter) : delay));
|
|
25
|
+
return fetchWithRetry(url, options, retriesRemaining - 1, delay * 2);
|
|
26
|
+
};
|
|
@@ -14,15 +14,6 @@ export const createSyncBlockNode = (localId, resourceId) => {
|
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
|
-
export const createBodiedSyncBlockNode = (localId, resourceId) => {
|
|
18
|
-
return {
|
|
19
|
-
type: 'bodiedSyncBlock',
|
|
20
|
-
attrs: {
|
|
21
|
-
localId,
|
|
22
|
-
resourceId
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
17
|
export const convertSyncBlockJSONNodeToSyncBlockNode = node => {
|
|
27
18
|
if (node.type !== 'syncBlock' || !node.attrs || !('localId' in node.attrs) || !('resourceId' in node.attrs) || typeof node.attrs.localId !== 'string' || typeof node.attrs.resourceId !== 'string') {
|
|
28
19
|
return undefined;
|
|
@@ -8,6 +8,7 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
8
8
|
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
9
9
|
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
10
10
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
11
|
+
import { fetchWithRetry } from '../../utils/retry';
|
|
11
12
|
export var isBlockContentResponse = function isBlockContentResponse(response) {
|
|
12
13
|
var content = response.content;
|
|
13
14
|
return typeof content === 'string';
|
|
@@ -62,7 +63,7 @@ export var getReferenceSyncedBlocks = /*#__PURE__*/function () {
|
|
|
62
63
|
while (1) switch (_context.prev = _context.next) {
|
|
63
64
|
case 0:
|
|
64
65
|
_context.next = 2;
|
|
65
|
-
return
|
|
66
|
+
return fetchWithRetry("".concat(BLOCK_SERVICE_API_URL, "/block/document/reference/").concat(encodeURIComponent(documentAri)), {
|
|
66
67
|
method: 'GET',
|
|
67
68
|
headers: COMMON_HEADERS
|
|
68
69
|
});
|
|
@@ -112,7 +113,7 @@ export var getSyncedBlockContent = /*#__PURE__*/function () {
|
|
|
112
113
|
case 0:
|
|
113
114
|
blockAri = _ref2.blockAri;
|
|
114
115
|
_context2.next = 3;
|
|
115
|
-
return
|
|
116
|
+
return fetchWithRetry("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(encodeURIComponent(blockAri)), {
|
|
116
117
|
method: 'GET',
|
|
117
118
|
headers: COMMON_HEADERS
|
|
118
119
|
});
|
|
@@ -146,7 +147,7 @@ export var deleteSyncedBlock = /*#__PURE__*/function () {
|
|
|
146
147
|
case 0:
|
|
147
148
|
blockAri = _ref4.blockAri;
|
|
148
149
|
_context3.next = 3;
|
|
149
|
-
return
|
|
150
|
+
return fetchWithRetry("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(encodeURIComponent(blockAri)), {
|
|
150
151
|
method: 'DELETE',
|
|
151
152
|
headers: COMMON_HEADERS
|
|
152
153
|
});
|
|
@@ -175,7 +176,7 @@ export var updateSyncedBlock = /*#__PURE__*/function () {
|
|
|
175
176
|
case 0:
|
|
176
177
|
blockAri = _ref6.blockAri, content = _ref6.content;
|
|
177
178
|
_context4.next = 3;
|
|
178
|
-
return
|
|
179
|
+
return fetchWithRetry("".concat(BLOCK_SERVICE_API_URL, "/block/").concat(encodeURIComponent(blockAri)), {
|
|
179
180
|
method: 'PUT',
|
|
180
181
|
headers: COMMON_HEADERS,
|
|
181
182
|
body: JSON.stringify({
|
|
@@ -207,7 +208,7 @@ export var createSyncedBlock = /*#__PURE__*/function () {
|
|
|
207
208
|
case 0:
|
|
208
209
|
blockAri = _ref8.blockAri, blockInstanceId = _ref8.blockInstanceId, sourceAri = _ref8.sourceAri, product = _ref8.product, content = _ref8.content;
|
|
209
210
|
_context5.next = 3;
|
|
210
|
-
return
|
|
211
|
+
return fetchWithRetry("".concat(BLOCK_SERVICE_API_URL, "/block"), {
|
|
211
212
|
method: 'POST',
|
|
212
213
|
headers: COMMON_HEADERS,
|
|
213
214
|
body: JSON.stringify({
|
|
@@ -3,6 +3,7 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
3
3
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
4
4
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
5
5
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6
|
+
import { fetchWithRetry } from '../../utils/retry';
|
|
6
7
|
import { getConfluencePageAri } from './ari';
|
|
7
8
|
import { isBlogPageType } from './utils';
|
|
8
9
|
var COMMON_HEADERS = {
|
|
@@ -88,7 +89,7 @@ export var getContentProperty = /*#__PURE__*/function () {
|
|
|
88
89
|
}
|
|
89
90
|
};
|
|
90
91
|
_context.next = 6;
|
|
91
|
-
return
|
|
92
|
+
return fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
92
93
|
method: 'POST',
|
|
93
94
|
headers: _objectSpread(_objectSpread({}, COMMON_HEADERS), AGG_HEADERS),
|
|
94
95
|
body: JSON.stringify(bodyData)
|
|
@@ -197,7 +198,7 @@ export var createContentProperty = /*#__PURE__*/function () {
|
|
|
197
198
|
}
|
|
198
199
|
};
|
|
199
200
|
_context3.next = 6;
|
|
200
|
-
return
|
|
201
|
+
return fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
201
202
|
method: 'POST',
|
|
202
203
|
headers: _objectSpread(_objectSpread({}, COMMON_HEADERS), AGG_HEADERS),
|
|
203
204
|
body: JSON.stringify(bodyData)
|
|
@@ -247,7 +248,7 @@ export var deleteContentProperty = /*#__PURE__*/function () {
|
|
|
247
248
|
}
|
|
248
249
|
};
|
|
249
250
|
_context4.next = 6;
|
|
250
|
-
return
|
|
251
|
+
return fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
251
252
|
method: 'POST',
|
|
252
253
|
headers: _objectSpread(_objectSpread({}, COMMON_HEADERS), AGG_HEADERS),
|
|
253
254
|
body: JSON.stringify(bodyData)
|
|
@@ -7,6 +7,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
7
7
|
|
|
8
8
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
9
9
|
import { getSourceInfoErrorPayload } from '../../utils/errorHandling';
|
|
10
|
+
import { fetchWithRetry } from '../../utils/retry';
|
|
10
11
|
import { getPageIdAndTypeFromConfluencePageAri } from './ari';
|
|
11
12
|
import { isBlogPageType } from './utils';
|
|
12
13
|
var COMMON_HEADERS = {
|
|
@@ -38,7 +39,7 @@ var getConfluenceSourceInfo = /*#__PURE__*/function () {
|
|
|
38
39
|
}
|
|
39
40
|
};
|
|
40
41
|
_context.next = 3;
|
|
41
|
-
return
|
|
42
|
+
return fetchWithRetry(GRAPHQL_ENDPOINT, {
|
|
42
43
|
method: 'POST',
|
|
43
44
|
headers: _objectSpread(_objectSpread({}, COMMON_HEADERS), AGG_HEADERS),
|
|
44
45
|
body: JSON.stringify(bodyData)
|
package/dist/esm/common/types.js
CHANGED
|
@@ -2,6 +2,11 @@ export var SyncBlockError = /*#__PURE__*/function (SyncBlockError) {
|
|
|
2
2
|
SyncBlockError["Errored"] = "errored";
|
|
3
3
|
SyncBlockError["NotFound"] = "not_found";
|
|
4
4
|
SyncBlockError["Forbidden"] = "forbidden";
|
|
5
|
+
SyncBlockError["InvalidRequest"] = "invalid_request";
|
|
6
|
+
SyncBlockError["RateLimited"] = "rate_limited";
|
|
7
|
+
SyncBlockError["Conflict"] = "conflict";
|
|
8
|
+
// attempt to create block that already exists
|
|
9
|
+
SyncBlockError["ServerError"] = "server_error";
|
|
5
10
|
SyncBlockError["InvalidContent"] = "invalid_content"; // content is not a valid JSON
|
|
6
11
|
return SyncBlockError;
|
|
7
12
|
}({});
|