@atlaskit/editor-synced-block-provider 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/common/rebase-transaction.js +31 -0
  3. package/dist/cjs/common/syncBlockProvider.js +24 -12
  4. package/dist/cjs/common/syncBlockStoreManager.js +24 -11
  5. package/dist/cjs/index.js +34 -1
  6. package/dist/cjs/providers/confluenceContentAPI.js +238 -0
  7. package/dist/cjs/utils/ari.js +42 -0
  8. package/dist/cjs/utils/contentProperty.js +192 -0
  9. package/dist/es2019/common/rebase-transaction.js +26 -0
  10. package/dist/es2019/common/syncBlockProvider.js +25 -13
  11. package/dist/es2019/common/syncBlockStoreManager.js +18 -7
  12. package/dist/es2019/index.js +5 -2
  13. package/dist/es2019/providers/confluenceContentAPI.js +150 -0
  14. package/dist/es2019/utils/ari.js +32 -0
  15. package/dist/es2019/utils/contentProperty.js +160 -0
  16. package/dist/esm/common/rebase-transaction.js +26 -0
  17. package/dist/esm/common/syncBlockProvider.js +24 -12
  18. package/dist/esm/common/syncBlockStoreManager.js +24 -11
  19. package/dist/esm/index.js +5 -2
  20. package/dist/esm/providers/confluenceContentAPI.js +232 -0
  21. package/dist/esm/utils/ari.js +36 -0
  22. package/dist/esm/utils/contentProperty.js +185 -0
  23. package/dist/types/common/rebase-transaction.d.ts +11 -0
  24. package/dist/types/common/syncBlockProvider.d.ts +3 -1
  25. package/dist/types/common/syncBlockStoreManager.d.ts +5 -2
  26. package/dist/types/common/types.d.ts +1 -0
  27. package/dist/types/index.d.ts +5 -2
  28. package/dist/types/providers/confluenceContentAPI.d.ts +41 -0
  29. package/dist/types/utils/ari.d.ts +10 -0
  30. package/dist/types/utils/contentProperty.d.ts +61 -0
  31. package/dist/types-ts4.5/common/rebase-transaction.d.ts +11 -0
  32. package/dist/types-ts4.5/common/syncBlockProvider.d.ts +3 -1
  33. package/dist/types-ts4.5/common/syncBlockStoreManager.d.ts +5 -2
  34. package/dist/types-ts4.5/common/types.d.ts +1 -0
  35. package/dist/types-ts4.5/index.d.ts +5 -2
  36. package/dist/types-ts4.5/providers/confluenceContentAPI.d.ts +41 -0
  37. package/dist/types-ts4.5/utils/ari.d.ts +10 -0
  38. package/dist/types-ts4.5/utils/contentProperty.d.ts +61 -0
  39. package/package.json +2 -2
@@ -0,0 +1,160 @@
1
+ import { getConfluencePageAri } from './ari';
2
+ const COMMON_HEADERS = {
3
+ 'Content-Type': 'application/json',
4
+ Accept: 'application/json'
5
+ };
6
+ const AGG_HEADERS = {
7
+ 'X-ExperimentalApi': 'confluence-agg-beta'
8
+ };
9
+ const GRAPHQL_ENDPOINT = '/gateway/api/graphql';
10
+ const GET_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_GET';
11
+ const CREATE_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_CREATE';
12
+ const UPDATE_OPERATION_NAME = 'EDITOR_SYNCED_BLOCK_UPDATE';
13
+ /**
14
+ * Query to get the page property by key
15
+ * @param documentARI
16
+ * @param key
17
+ * @returns
18
+ */
19
+ const GET_QUERY = `query ${GET_OPERATION_NAME} ($id: ID!, $keys: [String]!) {
20
+ confluence {
21
+ page (id: $id) {
22
+ properties(keys: $keys) {
23
+ key,
24
+ value
25
+ }
26
+ }
27
+ }
28
+ }`;
29
+
30
+ /**
31
+ * Query to create a page property with key and value
32
+ * @param documentARI
33
+ * @param key
34
+ * @param value
35
+ * @returns
36
+ */
37
+ const CREATE_QUERY = `mutation ${CREATE_OPERATION_NAME} ($input: ConfluenceCreatePagePropertyInput!){
38
+ confluence {
39
+ createPageProperty(input: $input) {
40
+ pageProperty {
41
+ key,
42
+ value
43
+ }
44
+ }
45
+ }
46
+ }`;
47
+
48
+ /**
49
+ * Query to update a page property with key and value without bumping the version
50
+ * @param documentARI
51
+ * @param key
52
+ * @param value
53
+ * @returns
54
+ */
55
+ const UPDATE_QUERY = `mutation ${UPDATE_OPERATION_NAME} ($input: ConfluenceUpdateValuePagePropertyInput!) {
56
+ confluence {
57
+ updateValuePageProperty(input: $input) {
58
+ pageProperty {
59
+ key,
60
+ value
61
+ }
62
+ }
63
+ }
64
+ }`;
65
+ export const getContentProperty = async ({
66
+ pageId,
67
+ key,
68
+ cloudId
69
+ }) => {
70
+ const documentARI = getConfluencePageAri(pageId, cloudId);
71
+ const bodyData = {
72
+ query: GET_QUERY,
73
+ operationName: GET_OPERATION_NAME,
74
+ variables: {
75
+ id: documentARI,
76
+ keys: [key]
77
+ }
78
+ };
79
+ const response = await fetch(GRAPHQL_ENDPOINT, {
80
+ method: 'POST',
81
+ headers: {
82
+ ...COMMON_HEADERS,
83
+ ...AGG_HEADERS
84
+ },
85
+ body: JSON.stringify(bodyData)
86
+ });
87
+ if (!response.ok) {
88
+ throw new Error(`Failed to get content property: ${response.statusText}`);
89
+ }
90
+ const contentProperty = await response.json();
91
+ return contentProperty;
92
+ };
93
+ export const updateContentProperty = async ({
94
+ pageId,
95
+ key,
96
+ value,
97
+ cloudId
98
+ }) => {
99
+ const documentARI = getConfluencePageAri(pageId, cloudId);
100
+ const bodyData = {
101
+ query: UPDATE_QUERY,
102
+ operationName: UPDATE_OPERATION_NAME,
103
+ variables: {
104
+ input: {
105
+ pageId: documentARI,
106
+ key,
107
+ value,
108
+ useSameVersion: true
109
+ }
110
+ }
111
+ };
112
+ const response = await fetch(GRAPHQL_ENDPOINT, {
113
+ method: 'POST',
114
+ headers: {
115
+ ...COMMON_HEADERS,
116
+ ...AGG_HEADERS
117
+ },
118
+ body: JSON.stringify(bodyData)
119
+ });
120
+ if (!response.ok) {
121
+ throw new Error(`Failed to update content property: ${response.statusText}`);
122
+ }
123
+ const contentProperty = await response.json();
124
+ return contentProperty;
125
+ };
126
+ export const createContentProperty = async ({
127
+ pageId,
128
+ key,
129
+ value,
130
+ cloudId
131
+ }) => {
132
+ const documentARI = getConfluencePageAri(pageId, cloudId);
133
+
134
+ // eslint-disable-next-line require-unicode-regexp
135
+ const escapedValue = value.replace(/"/g, '\\"');
136
+ const bodyData = {
137
+ query: CREATE_QUERY,
138
+ operationName: CREATE_OPERATION_NAME,
139
+ variables: {
140
+ input: {
141
+ pageId: documentARI,
142
+ key,
143
+ value: escapedValue
144
+ }
145
+ }
146
+ };
147
+ const response = await fetch(GRAPHQL_ENDPOINT, {
148
+ method: 'POST',
149
+ headers: {
150
+ ...COMMON_HEADERS,
151
+ ...AGG_HEADERS
152
+ },
153
+ body: JSON.stringify(bodyData)
154
+ });
155
+ if (!response.ok) {
156
+ throw new Error(`Failed to create content property: ${response.statusText}`);
157
+ }
158
+ const contentProperty = await response.json();
159
+ return contentProperty;
160
+ };
@@ -0,0 +1,26 @@
1
+ import { Mapping } from '@atlaskit/editor-prosemirror/transform';
2
+
3
+ /**
4
+ * Rebase `currentTr` over `incomingTr` based on the provided `state`.
5
+ * This function adjusts the steps in `currentTr` to account for the changes made by `incomingTr`.
6
+ *
7
+ * @param currentTr - The transaction to be rebased.
8
+ * @param incomingTr - The transaction that has already been applied to the state.
9
+ * @param state - The editor state after applying `incomingTr`.
10
+ * @returns A new transaction that represents `currentTr` rebased over `incomingTr`.
11
+ */
12
+ export var rebaseTransaction = function rebaseTransaction(currentTr, incomingTr, state) {
13
+ if (!incomingTr.docChanged) {
14
+ return currentTr;
15
+ }
16
+ var currentMapping = new Mapping(incomingTr.mapping.maps);
17
+ var rebasedTransaction = state.tr;
18
+ currentTr.steps.forEach(function (step) {
19
+ var mappedStep = step.map(currentMapping);
20
+ if (mappedStep) {
21
+ rebasedTransaction.step(mappedStep);
22
+ currentMapping.appendMap(mappedStep.getMap());
23
+ }
24
+ });
25
+ return rebasedTransaction;
26
+ };
@@ -9,7 +9,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
9
9
  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; }
10
10
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
11
11
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
12
- import { useEffect, useState } from 'react';
12
+ import { useEffect, useState, useMemo } from 'react';
13
13
  import { convertSyncBlockPMNodeToSyncBlockData } from '../utils/utils';
14
14
  import { SyncBlockDataProvider } from './types';
15
15
  export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
@@ -48,6 +48,9 @@ export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
48
48
  });
49
49
  return Promise.all(resourceIds);
50
50
  });
51
+ _defineProperty(_this, "getSourceId", function () {
52
+ return _this.sourceId;
53
+ });
51
54
  _this.fetchProvider = fetchProvider;
52
55
  _this.writeProvider = writeProvider;
53
56
  _this.sourceId = sourceId;
@@ -61,25 +64,34 @@ export var useFetchDocNode = function useFetchDocNode(editorView, node, defaultD
61
64
  _useState2 = _slicedToArray(_useState, 2),
62
65
  docNode = _useState2[0],
63
66
  setDocNode = _useState2[1];
67
+ var fetchNode = function fetchNode(editorView, node, provider) {
68
+ var nodes = [convertSyncBlockPMNodeToSyncBlockData(node, false)];
69
+ provider === null || provider === void 0 || provider.fetchNodesData(nodes).then(function (data) {
70
+ var _data$;
71
+ if (data && (_data$ = data[0]) !== null && _data$ !== void 0 && _data$.content) {
72
+ var newNode = editorView.state.schema.nodeFromJSON(data[0].content);
73
+ setDocNode(_objectSpread(_objectSpread({}, newNode.toJSON()), {}, {
74
+ version: 1
75
+ }));
76
+ }
77
+ });
78
+ };
64
79
  useEffect(function () {
65
80
  if (!provider) {
66
81
  return;
67
82
  }
83
+ fetchNode(editorView, node, provider);
68
84
  var interval = window.setInterval(function () {
69
- var nodes = [convertSyncBlockPMNodeToSyncBlockData(node, false)];
70
- provider === null || provider === void 0 || provider.fetchNodesData(nodes).then(function (data) {
71
- var _data$;
72
- if (data && (_data$ = data[0]) !== null && _data$ !== void 0 && _data$.content) {
73
- var newNode = editorView.state.schema.nodeFromJSON(data[0].content);
74
- setDocNode(_objectSpread(_objectSpread({}, newNode.toJSON()), {}, {
75
- version: 1
76
- }));
77
- }
78
- });
79
- }, 1000);
85
+ fetchNode(editorView, node, provider);
86
+ }, 3000);
80
87
  return function () {
81
88
  window.clearInterval(interval);
82
89
  };
83
90
  }, [editorView, node, provider]);
84
91
  return docNode;
92
+ };
93
+ export var useMemoizedSyncedBlockProvider = function useMemoizedSyncedBlockProvider(fetchProvider, writeProvider, sourceId) {
94
+ return useMemo(function () {
95
+ return new SyncBlockProvider(fetchProvider, writeProvider, sourceId);
96
+ }, [fetchProvider, writeProvider, sourceId]);
85
97
  };
@@ -3,6 +3,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
3
  import _createClass from "@babel/runtime/helpers/createClass";
4
4
  import _regeneratorRuntime from "@babel/runtime/regenerator";
5
5
  import uuid from 'uuid';
6
+ import { rebaseTransaction as _rebaseTransaction } from './rebase-transaction';
6
7
 
7
8
  // Do this typedef to make it clear that
8
9
  // this is a local identifier for a resource for local use
@@ -13,9 +14,10 @@ import uuid from 'uuid';
13
14
  // Handles caching, debouncing updates, and publish/subscribe for local changes.
14
15
  // Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
15
16
  export var SyncBlockStoreManager = /*#__PURE__*/function () {
16
- function SyncBlockStoreManager(_dataProvider) {
17
+ function SyncBlockStoreManager(dataProvider) {
17
18
  _classCallCheck(this, SyncBlockStoreManager);
18
19
  this.syncBlocks = new Map();
20
+ this.dataProvider = dataProvider;
19
21
  }
20
22
  return _createClass(SyncBlockStoreManager, [{
21
23
  key: "setEditorView",
@@ -25,14 +27,13 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
25
27
  }, {
26
28
  key: "isSourceBlock",
27
29
  value: function isSourceBlock(node) {
28
- var _this$syncBlocks$get;
29
30
  if (node.type.name !== 'syncBlock') {
30
31
  return false;
31
32
  }
32
33
  var _node$attrs = node.attrs,
33
34
  resourceId = _node$attrs.resourceId,
34
35
  localId = _node$attrs.localId;
35
- return this.syncBlocks.has(resourceId) && ((_this$syncBlocks$get = this.syncBlocks.get(resourceId)) === null || _this$syncBlocks$get === void 0 ? void 0 : _this$syncBlocks$get.sourceLocalId) === localId;
36
+ return resourceId.includes(localId);
36
37
  }
37
38
  }, {
38
39
  key: "registerConfirmationCallback",
@@ -51,15 +52,18 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
51
52
  }, {
52
53
  key: "createSyncBlockNode",
53
54
  value: function createSyncBlockNode() {
55
+ var _this$dataProvider;
54
56
  // TODO: EDITOR-1644 - properly implement creation of the synced block
55
57
  // below is a temporary implementation for the creation of the synced block
56
58
  // the resource id needs to have pageId and content property key in it
59
+ // Note: If the data provider is not set, the resource id will be the local id
57
60
 
58
- var blockInstanceId = uuid();
59
61
  var localId = uuid();
62
+ var sourceId = (_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.getSourceId();
63
+ var resourceId = sourceId ? "".concat(sourceId, "/").concat(localId) : localId;
60
64
  var syncBlockNode = {
61
65
  attrs: {
62
- resourceId: "ari:cloud:confluence:fake_cloud_id:page/fake_page_id/".concat(blockInstanceId),
66
+ resourceId: resourceId,
63
67
  localId: localId
64
68
  },
65
69
  type: 'syncBlock'
@@ -80,23 +84,24 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
80
84
  while (1) switch (_context.prev = _context.next) {
81
85
  case 0:
82
86
  if (!this.confirmationCallback) {
83
- _context.next = 5;
87
+ _context.next = 7;
84
88
  break;
85
89
  }
86
- _context.next = 3;
90
+ this.confirmationTransaction = tr;
91
+ _context.next = 4;
87
92
  return this.confirmationCallback();
88
- case 3:
93
+ case 4:
89
94
  confirmed = _context.sent;
90
95
  if (confirmed) {
91
- // TODO: EDITOR-1779 - "rebase" the transaction to reflect the latest document state
92
- (_this$editorView = this.editorView) === null || _this$editorView === void 0 || _this$editorView.dispatch(tr.setMeta('isConfirmedSyncBlockDeletion', true));
96
+ (_this$editorView = this.editorView) === null || _this$editorView === void 0 || _this$editorView.dispatch(this.confirmationTransaction.setMeta('isConfirmedSyncBlockDeletion', true));
93
97
  // Need to update the BE on deletion
94
98
  syncBlockIds.forEach(function (_ref) {
95
99
  var resourceId = _ref.resourceId;
96
100
  return _this2.syncBlocks.delete(resourceId);
97
101
  });
98
102
  }
99
- case 5:
103
+ this.confirmationTransaction = undefined;
104
+ case 7:
100
105
  case "end":
101
106
  return _context.stop();
102
107
  }
@@ -107,5 +112,13 @@ export var SyncBlockStoreManager = /*#__PURE__*/function () {
107
112
  }
108
113
  return deleteSyncBlocksWithConfirmation;
109
114
  }()
115
+ }, {
116
+ key: "rebaseTransaction",
117
+ value: function rebaseTransaction(incomingTr, state) {
118
+ if (!this.confirmationTransaction) {
119
+ return;
120
+ }
121
+ this.confirmationTransaction = _rebaseTransaction(this.confirmationTransaction, incomingTr, state);
122
+ }
110
123
  }]);
111
124
  }();
package/dist/esm/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  /* eslint-disable @atlaskit/editor/no-re-export */
2
2
 
3
- export { SyncBlockProvider as SyncedBlockProvider, useFetchDocNode } from './common/syncBlockProvider';
3
+ export { SyncBlockProvider as SyncedBlockProvider, useFetchDocNode, useMemoizedSyncedBlockProvider } from './common/syncBlockProvider';
4
4
  export { SyncBlockStoreManager } from './common/syncBlockStoreManager';
5
5
  export { inMemoryFetchProvider, inMemoryWriteProvider } from './providers/inMemory';
6
+ export { getDefaultSyncBlockSchema } from './common/schema';
7
+ export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluenceContentAPI';
8
+ export { getConfluencePageAri } from './utils/ari';
6
9
  export { convertSyncBlockPMNodeToSyncBlockData, generateSyncBlockSourceUrl } from './utils/utils';
7
- export { getDefaultSyncBlockSchema } from './common/schema';
10
+ export { rebaseTransaction } from './common/rebase-transaction';
@@ -0,0 +1,232 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
+ import _createClass from "@babel/runtime/helpers/createClass";
5
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
6
+ import { useMemo } from 'react';
7
+ import { getLocalIdFromAri, getPageIdFromAri } from '../utils/ari';
8
+ import { getContentProperty, createContentProperty, updateContentProperty } from '../utils/contentProperty';
9
+
10
+ /**
11
+ * Configuration for Content API providers
12
+ */
13
+
14
+ var getContentPropertyKey = function getContentPropertyKey(contentPropertyKey, localId) {
15
+ return contentPropertyKey + '-' + localId;
16
+ };
17
+ var parseSyncedBlockContentPropertyValue = function parseSyncedBlockContentPropertyValue(value) {
18
+ try {
19
+ if (typeof value === 'string') {
20
+ return JSON.parse(value);
21
+ }
22
+ return value;
23
+ } catch (error) {
24
+ // eslint-disable-next-line no-console
25
+ console.error('Failed to parse synced block content:', error);
26
+ return {
27
+ content: undefined
28
+ };
29
+ }
30
+ };
31
+
32
+ /**
33
+ * ADFFetchProvider implementation that fetches synced block data from Confluence Content API
34
+ */
35
+ var ConfluenceADFFetchProvider = /*#__PURE__*/function () {
36
+ function ConfluenceADFFetchProvider(config) {
37
+ _classCallCheck(this, ConfluenceADFFetchProvider);
38
+ this.config = config;
39
+ }
40
+ return _createClass(ConfluenceADFFetchProvider, [{
41
+ key: "fetchData",
42
+ value: function () {
43
+ var _fetchData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(resourceId) {
44
+ var _contentProperty$data, pageId, localId, key, options, contentProperty, value, syncedBlockData;
45
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
46
+ while (1) switch (_context.prev = _context.next) {
47
+ case 0:
48
+ _context.prev = 0;
49
+ pageId = getPageIdFromAri(resourceId);
50
+ localId = getLocalIdFromAri(resourceId);
51
+ key = getContentPropertyKey(this.config.contentPropertyKey, localId);
52
+ options = {
53
+ pageId: pageId,
54
+ key: key,
55
+ cloudId: this.config.cloudId
56
+ };
57
+ _context.next = 7;
58
+ return getContentProperty(options);
59
+ case 7:
60
+ contentProperty = _context.sent;
61
+ value = (_contentProperty$data = contentProperty.data.confluence.page.properties) === null || _contentProperty$data === void 0 || (_contentProperty$data = _contentProperty$data[0]) === null || _contentProperty$data === void 0 ? void 0 : _contentProperty$data.value;
62
+ if (value) {
63
+ _context.next = 11;
64
+ break;
65
+ }
66
+ throw new Error('Content property value does not exist');
67
+ case 11:
68
+ // Parse the synced block content from the property value
69
+ syncedBlockData = parseSyncedBlockContentPropertyValue(value);
70
+ return _context.abrupt("return", {
71
+ content: syncedBlockData.content
72
+ });
73
+ case 15:
74
+ _context.prev = 15;
75
+ _context.t0 = _context["catch"](0);
76
+ // eslint-disable-next-line no-console
77
+ console.error('Failed to fetch synced block data:', _context.t0);
78
+ return _context.abrupt("return", {
79
+ content: undefined
80
+ });
81
+ case 19:
82
+ case "end":
83
+ return _context.stop();
84
+ }
85
+ }, _callee, this, [[0, 15]]);
86
+ }));
87
+ function fetchData(_x) {
88
+ return _fetchData.apply(this, arguments);
89
+ }
90
+ return fetchData;
91
+ }()
92
+ }]);
93
+ }();
94
+ /**
95
+ * ADFWriteProvider implementation that writes synced block data to Confluence Content API
96
+ */
97
+ var ConfluenceADFWriteProvider = /*#__PURE__*/function () {
98
+ function ConfluenceADFWriteProvider(config) {
99
+ var _this = this;
100
+ _classCallCheck(this, ConfluenceADFWriteProvider);
101
+ _defineProperty(this, "createNewContentProperty", /*#__PURE__*/function () {
102
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(pageId, key, value) {
103
+ var _contentProperty$data2;
104
+ var contentProperty;
105
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
106
+ while (1) switch (_context2.prev = _context2.next) {
107
+ case 0:
108
+ _context2.next = 2;
109
+ return createContentProperty({
110
+ pageId: pageId,
111
+ key: key,
112
+ value: value,
113
+ cloudId: _this.config.cloudId
114
+ });
115
+ case 2:
116
+ contentProperty = _context2.sent;
117
+ if (!(((_contentProperty$data2 = contentProperty.data.confluence.createPageProperty.pageProperty) === null || _contentProperty$data2 === void 0 ? void 0 : _contentProperty$data2.key) === key)) {
118
+ _context2.next = 7;
119
+ break;
120
+ }
121
+ return _context2.abrupt("return", key);
122
+ case 7:
123
+ throw new Error('Failed to create content property');
124
+ case 8:
125
+ case "end":
126
+ return _context2.stop();
127
+ }
128
+ }, _callee2);
129
+ }));
130
+ return function (_x2, _x3, _x4) {
131
+ return _ref.apply(this, arguments);
132
+ };
133
+ }());
134
+ this.config = config;
135
+ }
136
+ return _createClass(ConfluenceADFWriteProvider, [{
137
+ key: "writeData",
138
+ value: function () {
139
+ var _writeData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(sourceId, localId, data, resourceId) {
140
+ var pageId, syncedBlockValue, _contentProperty$data3, _localId, key, contentProperty, _key;
141
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
142
+ while (1) switch (_context3.prev = _context3.next) {
143
+ case 0:
144
+ _context3.prev = 0;
145
+ pageId = getPageIdFromAri(sourceId);
146
+ syncedBlockValue = JSON.stringify({
147
+ content: data
148
+ });
149
+ if (!resourceId) {
150
+ _context3.next = 20;
151
+ break;
152
+ }
153
+ // Update existing content property
154
+ _localId = getLocalIdFromAri(resourceId);
155
+ key = getContentPropertyKey(this.config.contentPropertyKey, _localId);
156
+ _context3.next = 8;
157
+ return updateContentProperty({
158
+ pageId: pageId,
159
+ key: key,
160
+ value: syncedBlockValue,
161
+ cloudId: this.config.cloudId
162
+ });
163
+ case 8:
164
+ contentProperty = _context3.sent;
165
+ if (!(((_contentProperty$data3 = contentProperty.data.confluence.updateValuePageProperty.pageProperty) === null || _contentProperty$data3 === void 0 ? void 0 : _contentProperty$data3.key) === key)) {
166
+ _context3.next = 13;
167
+ break;
168
+ }
169
+ return _context3.abrupt("return", key);
170
+ case 13:
171
+ if (!(contentProperty.data.confluence.updateValuePageProperty.pageProperty === null)) {
172
+ _context3.next = 17;
173
+ break;
174
+ }
175
+ return _context3.abrupt("return", this.createNewContentProperty(pageId, key, syncedBlockValue));
176
+ case 17:
177
+ throw new Error('Failed to update content property');
178
+ case 18:
179
+ _context3.next = 22;
180
+ break;
181
+ case 20:
182
+ // Create new content property
183
+ _key = getContentPropertyKey(this.config.contentPropertyKey, localId);
184
+ return _context3.abrupt("return", this.createNewContentProperty(pageId, _key, syncedBlockValue));
185
+ case 22:
186
+ _context3.next = 28;
187
+ break;
188
+ case 24:
189
+ _context3.prev = 24;
190
+ _context3.t0 = _context3["catch"](0);
191
+ // eslint-disable-next-line no-console
192
+ console.error('Failed to write synced block data:', _context3.t0);
193
+ return _context3.abrupt("return", Promise.reject(_context3.t0));
194
+ case 28:
195
+ case "end":
196
+ return _context3.stop();
197
+ }
198
+ }, _callee3, this, [[0, 24]]);
199
+ }));
200
+ function writeData(_x5, _x6, _x7, _x8) {
201
+ return _writeData.apply(this, arguments);
202
+ }
203
+ return writeData;
204
+ }()
205
+ }]);
206
+ }();
207
+ /**
208
+ * Factory function to create both providers with shared configuration
209
+ */
210
+ var createContentAPIProviders = function createContentAPIProviders(config) {
211
+ var fetchProvider = new ConfluenceADFFetchProvider(config);
212
+ var writeProvider = new ConfluenceADFWriteProvider(config);
213
+ return {
214
+ fetchProvider: fetchProvider,
215
+ writeProvider: writeProvider
216
+ };
217
+ };
218
+
219
+ /**
220
+ * Convenience function to create providers with default content property key
221
+ */
222
+ export var createContentAPIProvidersWithDefaultKey = function createContentAPIProvidersWithDefaultKey(cloudId) {
223
+ return createContentAPIProviders({
224
+ cloudId: cloudId,
225
+ contentPropertyKey: 'editor-synced-block'
226
+ });
227
+ };
228
+ export var useMemoizedContentAPIProviders = function useMemoizedContentAPIProviders(cloudId) {
229
+ return useMemo(function () {
230
+ return createContentAPIProvidersWithDefaultKey(cloudId);
231
+ }, [cloudId]);
232
+ };
@@ -0,0 +1,36 @@
1
+ export var getConfluencePageAri = function getConfluencePageAri(pageId, cloudId) {
2
+ return "ari:cloud:confluence:".concat(cloudId, ":page/").concat(pageId);
3
+ };
4
+ export var getPageIdFromAri = function getPageIdFromAri(ari) {
5
+ // eslint-disable-next-line require-unicode-regexp
6
+ var match = ari.match(/ari:cloud:confluence:[^:]+:page\/(\d+)/);
7
+ if (match !== null && match !== void 0 && match[1]) {
8
+ return match[1];
9
+ }
10
+ throw new Error("Invalid page ARI: ".concat(ari));
11
+ };
12
+
13
+ /**
14
+ *
15
+ * @param ari ari:cloud:confluence:<cloudId>:page/<pageId>/<localId>
16
+ * @returns
17
+ */
18
+ export var getLocalIdFromAri = function getLocalIdFromAri(ari) {
19
+ // eslint-disable-next-line require-unicode-regexp
20
+ var match = ari.match(/ari:cloud:confluence:[^:]+:page\/\d+\/([a-zA-Z0-9-]+)/);
21
+ if (match !== null && match !== void 0 && match[1]) {
22
+ return match[1];
23
+ }
24
+ throw new Error("Invalid page ARI: ".concat(ari));
25
+ };
26
+ export var getContentPropertyAri = function getContentPropertyAri(contentPropertyId, cloudId) {
27
+ return "ari:cloud:confluence:".concat(cloudId, ":content/").concat(contentPropertyId);
28
+ };
29
+ export var getContentPropertyIdFromAri = function getContentPropertyIdFromAri(ari) {
30
+ // eslint-disable-next-line require-unicode-regexp
31
+ var match = ari.match(/ari:cloud:confluence:[^:]+:content\/([^/]+)/);
32
+ if (match) {
33
+ return match[1];
34
+ }
35
+ throw new Error("Invalid content property ARI: ".concat(ari));
36
+ };