@atlaskit/editor-synced-block-provider 2.1.2 → 2.2.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/common/types.js +2 -19
  3. package/dist/cjs/hooks/useFetchSyncBlockData.js +43 -0
  4. package/dist/cjs/hooks/useHandleContentChanges.js +13 -0
  5. package/dist/cjs/index.js +9 -7
  6. package/dist/cjs/providers/{confluenceContentAPI.js → confluence/confluenceContentAPI.js} +4 -4
  7. package/dist/cjs/{common → providers}/syncBlockProvider.js +1 -1
  8. package/dist/cjs/providers/types.js +23 -0
  9. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +123 -0
  10. package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +191 -0
  11. package/dist/cjs/store-manager/syncBlockStoreManager.js +111 -0
  12. package/dist/cjs/utils/utils.js +1 -17
  13. package/dist/es2019/common/types.js +1 -3
  14. package/dist/es2019/hooks/useFetchSyncBlockData.js +32 -0
  15. package/dist/es2019/hooks/useHandleContentChanges.js +7 -0
  16. package/dist/es2019/index.js +7 -5
  17. package/dist/es2019/providers/{confluenceContentAPI.js → confluence/confluenceContentAPI.js} +4 -4
  18. package/dist/es2019/{common → providers}/syncBlockProvider.js +1 -1
  19. package/dist/es2019/providers/types.js +2 -0
  20. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +83 -0
  21. package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +115 -0
  22. package/dist/es2019/store-manager/syncBlockStoreManager.js +79 -0
  23. package/dist/es2019/utils/utils.js +0 -13
  24. package/dist/esm/common/types.js +1 -17
  25. package/dist/esm/hooks/useFetchSyncBlockData.js +36 -0
  26. package/dist/esm/hooks/useHandleContentChanges.js +7 -0
  27. package/dist/esm/index.js +7 -5
  28. package/dist/esm/providers/{confluenceContentAPI.js → confluence/confluenceContentAPI.js} +4 -4
  29. package/dist/esm/{common → providers}/syncBlockProvider.js +1 -1
  30. package/dist/esm/providers/types.js +16 -0
  31. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +116 -0
  32. package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +184 -0
  33. package/dist/esm/store-manager/syncBlockStoreManager.js +105 -0
  34. package/dist/esm/utils/utils.js +0 -16
  35. package/dist/types/common/types.d.ts +12 -25
  36. package/dist/types/hooks/useFetchSyncBlockData.d.ts +4 -0
  37. package/dist/types/hooks/useHandleContentChanges.d.ts +3 -0
  38. package/dist/types/index.d.ts +9 -6
  39. package/dist/{types-ts4.5/providers → types/providers/confluence}/confluenceContentAPI.d.ts +2 -1
  40. package/dist/types/providers/{inMemory.d.ts → in-memory/inMemory.d.ts} +1 -1
  41. package/dist/types/{common → providers}/syncBlockProvider.d.ts +2 -1
  42. package/dist/types/providers/types.d.ts +17 -0
  43. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +23 -0
  44. package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +31 -0
  45. package/dist/types/store-manager/syncBlockStoreManager.d.ts +36 -0
  46. package/dist/types/utils/utils.d.ts +1 -2
  47. package/dist/types-ts4.5/common/types.d.ts +12 -25
  48. package/dist/types-ts4.5/hooks/useFetchSyncBlockData.d.ts +4 -0
  49. package/dist/types-ts4.5/hooks/useHandleContentChanges.d.ts +3 -0
  50. package/dist/types-ts4.5/index.d.ts +9 -6
  51. package/dist/{types/providers → types-ts4.5/providers/confluence}/confluenceContentAPI.d.ts +2 -1
  52. package/dist/types-ts4.5/providers/{inMemory.d.ts → in-memory/inMemory.d.ts} +1 -1
  53. package/dist/types-ts4.5/{common → providers}/syncBlockProvider.d.ts +2 -1
  54. package/dist/types-ts4.5/providers/types.d.ts +17 -0
  55. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +23 -0
  56. package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +31 -0
  57. package/dist/types-ts4.5/store-manager/syncBlockStoreManager.d.ts +36 -0
  58. package/dist/types-ts4.5/utils/utils.d.ts +1 -2
  59. package/package.json +3 -3
  60. package/dist/cjs/common/syncBlockStoreManager.js +0 -330
  61. package/dist/es2019/common/syncBlockStoreManager.js +0 -240
  62. package/dist/esm/common/syncBlockStoreManager.js +0 -323
  63. package/dist/types/common/syncBlockStoreManager.d.ts +0 -50
  64. package/dist/types-ts4.5/common/syncBlockStoreManager.d.ts +0 -50
  65. /package/dist/cjs/providers/{inMemory.js → in-memory/inMemory.js} +0 -0
  66. /package/dist/es2019/providers/{inMemory.js → in-memory/inMemory.js} +0 -0
  67. /package/dist/esm/providers/{inMemory.js → in-memory/inMemory.js} +0 -0
@@ -1,8 +1,6 @@
1
- import { NodeDataProvider } from '@atlaskit/node-data-provider';
2
1
  export let SyncBlockStatus = /*#__PURE__*/function (SyncBlockStatus) {
3
2
  SyncBlockStatus["Errored"] = "errored";
4
3
  SyncBlockStatus["NotFound"] = "not_found";
5
4
  SyncBlockStatus["Unauthorized"] = "unauthorized";
6
5
  return SyncBlockStatus;
7
- }({});
8
- export class SyncBlockDataProvider extends NodeDataProvider {}
6
+ }({});
@@ -0,0 +1,32 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { SyncBlockStatus } from '../common/types';
3
+ export const useFetchSyncBlockData = (manager, syncBlockNode) => {
4
+ const [fetchSyncBlockDataResult, setFetchSyncBlockDataResult] = useState(null);
5
+ const fetchSyncBlockNode = useCallback(() => {
6
+ manager.fetchSyncBlockData(syncBlockNode).then(data => {
7
+ if (data && 'status' in data) {
8
+ // if there is an error, we don't want to replace real existing data with the error data
9
+ if (!fetchSyncBlockDataResult || 'status' in fetchSyncBlockDataResult) {
10
+ setFetchSyncBlockDataResult(data);
11
+ }
12
+ } else {
13
+ setFetchSyncBlockDataResult(data !== null && data !== void 0 ? data : null);
14
+ }
15
+ }).catch(() => {
16
+ //TODO: EDITOR-1921 - add error analytics
17
+ if (!fetchSyncBlockDataResult || 'status' in fetchSyncBlockDataResult) {
18
+ setFetchSyncBlockDataResult({
19
+ status: SyncBlockStatus.Errored
20
+ });
21
+ }
22
+ });
23
+ }, [manager, syncBlockNode, fetchSyncBlockDataResult]);
24
+ useEffect(() => {
25
+ fetchSyncBlockNode();
26
+ const interval = window.setInterval(fetchSyncBlockNode, 3000);
27
+ return () => {
28
+ window.clearInterval(interval);
29
+ };
30
+ }, [fetchSyncBlockNode]);
31
+ return fetchSyncBlockDataResult;
32
+ };
@@ -0,0 +1,7 @@
1
+ import { useEffect } from 'react';
2
+ export const useHandleContentChanges = (manager, syncBlockNode) => {
3
+ useEffect(() => {
4
+ //TODO: EDITOR-1921 - add error analytics
5
+ manager.updateSyncBlockData(syncBlockNode);
6
+ }, [manager, syncBlockNode]);
7
+ };
@@ -1,11 +1,13 @@
1
1
  /* eslint-disable @atlaskit/editor/no-re-export */
2
2
 
3
- export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './common/syncBlockProvider';
4
- export { SyncBlockStoreManager, useFetchSyncBlockData, useHandleContentChanges } from './common/syncBlockStoreManager';
3
+ export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './providers/syncBlockProvider';
4
+ export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
5
+ export { useFetchSyncBlockData } from './hooks/useFetchSyncBlockData';
6
+ export { useHandleContentChanges } from './hooks/useHandleContentChanges';
5
7
  export { SyncBlockStatus } from './common/types';
6
- export { inMemoryFetchProvider, inMemoryWriteProvider } from './providers/inMemory';
8
+ export { inMemoryFetchProvider, inMemoryWriteProvider } from './providers/in-memory/inMemory';
7
9
  export { getDefaultSyncBlockSchema } from './common/schema';
8
- export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluenceContentAPI';
10
+ export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluence/confluenceContentAPI';
9
11
  export { getConfluencePageAri } from './utils/ari';
10
- export { convertSyncBlockPMNodeToSyncBlockNode as convertSyncBlockPMNodeToSyncBlockData } from './utils/utils';
12
+ export { convertSyncBlockPMNodeToSyncBlockData } from './utils/utils';
11
13
  export { rebaseTransaction } from './common/rebase-transaction';
@@ -1,9 +1,9 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { useMemo } from 'react';
3
- import { SyncBlockStatus } from '../common/types';
4
- import { getLocalIdFromAri, getPageIdAndTypeFromAri } from '../utils/ari';
5
- import { getContentProperty, createContentProperty, updateContentProperty } from '../utils/contentProperty';
6
- import { isBlogPageType } from '../utils/utils';
3
+ import { SyncBlockStatus } from '../../common/types';
4
+ import { getLocalIdFromAri, getPageIdAndTypeFromAri } from '../../utils/ari';
5
+ import { getContentProperty, createContentProperty, updateContentProperty } from '../../utils/contentProperty';
6
+ import { isBlogPageType } from '../../utils/utils';
7
7
 
8
8
  /**
9
9
  * Configuration for Content API providers
@@ -1,7 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { useMemo } from 'react';
3
+ import { SyncBlockDataProvider } from '../providers/types';
3
4
  import { getLocalIdFromAri, getPageARIFromResourceId } from '../utils/ari';
4
- import { SyncBlockDataProvider } from './types';
5
5
  export class SyncBlockProvider extends SyncBlockDataProvider {
6
6
  constructor(fetchProvider, writeProvider, sourceId) {
7
7
  super();
@@ -0,0 +1,2 @@
1
+ import { NodeDataProvider } from '@atlaskit/node-data-provider';
2
+ export class SyncBlockDataProvider extends NodeDataProvider {}
@@ -0,0 +1,83 @@
1
+ const createSyncBlockNode = (localId, resourceId) => {
2
+ return {
3
+ type: 'syncBlock',
4
+ attrs: {
5
+ localId,
6
+ resourceId
7
+ }
8
+ };
9
+ };
10
+ export class ReferenceSyncBlockStoreManager {
11
+ constructor(dataProvider) {
12
+ this.dataProvider = dataProvider;
13
+ this.syncBlockCache = new Map();
14
+ this.syncBlockURLRequests = new Map();
15
+ }
16
+
17
+ /**
18
+ *
19
+ * @param localId - The local ID of the sync block to get the source URL for
20
+ * @param resourceId - The resource ID of the sync block to get the source URL for
21
+ * Fetches source URl for a sync block and updates sync block data with the source URL asynchronously.
22
+ */
23
+ fetchSyncBlockSourceURL({
24
+ localId,
25
+ resourceId
26
+ }) {
27
+ if (!localId || !resourceId || !this.dataProvider) {
28
+ return;
29
+ }
30
+
31
+ // if the sync block is a reference block, we need to fetch the URL to the source
32
+ // we could optimise this further by checking if the sync block is on the same page as the source
33
+ if (!this.syncBlockURLRequests.get(localId)) {
34
+ this.syncBlockURLRequests.set(localId, true);
35
+ this.dataProvider.retrieveSyncBlockSourceUrl(createSyncBlockNode(localId, resourceId)).then(sourceURL => {
36
+ const existingSyncBlock = this.syncBlockCache.get(localId);
37
+ if (existingSyncBlock) {
38
+ existingSyncBlock.sourceURL = sourceURL;
39
+ }
40
+ }).finally(() => {
41
+ this.syncBlockURLRequests.set(localId, false);
42
+ });
43
+ }
44
+ }
45
+ async fetchSyncBlockData(syncBlockNode) {
46
+ if (!this.dataProvider) {
47
+ throw new Error('Data provider not set');
48
+ }
49
+ const syncNode = createSyncBlockNode(syncBlockNode.attrs.localId, syncBlockNode.attrs.resourceId);
50
+
51
+ // async fetch source URL if it is not already fetched
52
+ const existingSyncBlock = this.syncBlockCache.get(syncBlockNode.attrs.localId);
53
+ if (!(existingSyncBlock !== null && existingSyncBlock !== void 0 && existingSyncBlock.sourceURL)) {
54
+ this.fetchSyncBlockSourceURL({
55
+ localId: syncBlockNode.attrs.localId,
56
+ resourceId: syncBlockNode.attrs.resourceId
57
+ });
58
+ }
59
+ const data = await this.dataProvider.fetchNodesData([syncNode]);
60
+ if (!data) {
61
+ throw new Error('Failed to fetch sync block node data');
62
+ }
63
+ const fetchSyncBlockDataResult = data[0];
64
+ if (!('status' in fetchSyncBlockDataResult)) {
65
+ // only adds it to the map if it did not error out
66
+ this.syncBlockCache.set(syncBlockNode.attrs.localId, {
67
+ ...existingSyncBlock,
68
+ ...fetchSyncBlockDataResult
69
+ });
70
+ }
71
+ return fetchSyncBlockDataResult;
72
+ }
73
+
74
+ /**
75
+ * Get the URL for a sync block.
76
+ * @param localId - The local ID of the sync block to get the URL for
77
+ * @returns
78
+ */
79
+ getSyncBlockURL(localId) {
80
+ const syncBlock = this.syncBlockCache.get(localId);
81
+ return syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.sourceURL;
82
+ }
83
+ }
@@ -0,0 +1,115 @@
1
+ import uuid from 'uuid';
2
+ import { rebaseTransaction } from '../common/rebase-transaction';
3
+ import { resourceIdFromSourceAndLocalId } from '../utils/ari';
4
+ import { convertSyncBlockPMNodeToSyncBlockData } from '../utils/utils';
5
+ export class SourceSyncBlockStoreManager {
6
+ constructor(dataProvider) {
7
+ this.dataProvider = dataProvider;
8
+ this.syncBlockCache = new Map();
9
+ }
10
+
11
+ /**
12
+ * Add/update a sync block node to/from the local cache
13
+ * @param syncBlockNode - The sync block node to update
14
+ */
15
+ updateSyncBlockData(syncBlockNode) {
16
+ try {
17
+ const {
18
+ localId,
19
+ resourceId
20
+ } = syncBlockNode.attrs;
21
+ if (!localId || !resourceId) {
22
+ throw new Error('Local ID or resource ID is not set');
23
+ }
24
+ const syncBlockData = convertSyncBlockPMNodeToSyncBlockData(syncBlockNode);
25
+ this.syncBlockCache.set(localId, syncBlockData);
26
+ } catch {
27
+ //TODO: EDITOR-1921 - add error analytics
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Save content of bodiedSyncBlock nodes in local cache to backend
33
+ *
34
+ * @returns true if saving all nodes successfully, false if fail to save some/all nodes
35
+ */
36
+ async flushBodiedSyncBlocks() {
37
+ try {
38
+ if (!this.dataProvider) {
39
+ throw new Error('Data provider not set');
40
+ }
41
+ const bodiedSyncBlockNodes = [];
42
+ const bodiedSyncBlockData = [];
43
+ Array.from(this.syncBlockCache.values()).forEach(syncBlockData => {
44
+ bodiedSyncBlockNodes.push({
45
+ type: 'bodiedSyncBlock',
46
+ attrs: {
47
+ localId: syncBlockData.blockInstanceId,
48
+ resourceId: syncBlockData.resourceId
49
+ }
50
+ });
51
+ bodiedSyncBlockData.push(syncBlockData);
52
+ });
53
+ if (bodiedSyncBlockNodes.length === 0) {
54
+ return Promise.resolve(true);
55
+ }
56
+ const resourceIds = await this.dataProvider.writeNodesData(bodiedSyncBlockNodes, bodiedSyncBlockData);
57
+ return resourceIds.every(resourceId => resourceId !== undefined);
58
+ } catch {
59
+ //TODO: EDITOR-1921 - add error analytics
60
+ return false;
61
+ }
62
+ }
63
+ setEditorView(editorView) {
64
+ this.editorView = editorView;
65
+ }
66
+ registerConfirmationCallback(callback) {
67
+ this.confirmationCallback = callback;
68
+ return () => {
69
+ this.confirmationCallback = undefined;
70
+ };
71
+ }
72
+ requireConfirmationBeforeDelete() {
73
+ return !!this.confirmationCallback;
74
+ }
75
+ createSyncBlockNode() {
76
+ var _this$dataProvider;
77
+ const blockInstanceId = uuid();
78
+ const sourceId = (_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.getSourceId();
79
+ if (!sourceId) {
80
+ throw new Error('Provider of sync block plugin is not set');
81
+ }
82
+
83
+ // This should be generated by the data provider implementation as it differs between data providers
84
+ const resourceId = resourceIdFromSourceAndLocalId(sourceId, blockInstanceId);
85
+ const syncBlockNode = {
86
+ attrs: {
87
+ resourceId,
88
+ localId: blockInstanceId
89
+ },
90
+ type: 'bodiedSyncBlock'
91
+ };
92
+ return syncBlockNode;
93
+ }
94
+ async deleteSyncBlocksWithConfirmation(tr, syncBlockIds) {
95
+ if (this.confirmationCallback) {
96
+ this.confirmationTransaction = tr;
97
+ const confirmed = await this.confirmationCallback();
98
+ if (confirmed) {
99
+ var _this$editorView;
100
+ (_this$editorView = this.editorView) === null || _this$editorView === void 0 ? void 0 : _this$editorView.dispatch(this.confirmationTransaction.setMeta('isConfirmedSyncBlockDeletion', true));
101
+ // Need to update the BE on deletion
102
+ syncBlockIds.forEach(({
103
+ localId
104
+ }) => this.syncBlockCache.delete(localId));
105
+ }
106
+ this.confirmationTransaction = undefined;
107
+ }
108
+ }
109
+ rebaseTransaction(incomingTr, state) {
110
+ if (!this.confirmationTransaction) {
111
+ return;
112
+ }
113
+ this.confirmationTransaction = rebaseTransaction(this.confirmationTransaction, incomingTr, state);
114
+ }
115
+ }
@@ -0,0 +1,79 @@
1
+ import { ReferenceSyncBlockStoreManager } from './referenceSyncBlockStoreManager';
2
+ import { SourceSyncBlockStoreManager } from './sourceSyncBlockStoreManager';
3
+
4
+ // A store manager responsible for the lifecycle and state management of sync blocks in an editor instance.
5
+ // Supports create, read, update, and delete operations for sync blocks.
6
+ // Designed to manage local in-memory state and synchronize with an external data provider.
7
+ // Handles caching, debouncing updates, and publish/subscribe for local changes.
8
+ // Ensures consistency between local and remote state, and can be used in both editor and renderer contexts.
9
+ export class SyncBlockStoreManager {
10
+ constructor(dataProvider) {
11
+ this.referenceSyncBlockStoreManager = new ReferenceSyncBlockStoreManager(dataProvider);
12
+ this.sourceSyncBlockStoreManager = new SourceSyncBlockStoreManager(dataProvider);
13
+ }
14
+ fetchSyncBlockData(syncBlockNode) {
15
+ if (this.isSourceBlock(syncBlockNode)) {
16
+ return Promise.reject(new Error('Invalid sync block node type provided for fetchSyncBlockData'));
17
+ }
18
+ return this.referenceSyncBlockStoreManager.fetchSyncBlockData(syncBlockNode);
19
+ }
20
+
21
+ /**
22
+ * Add/update a sync block node to/from the local cache
23
+ * @param syncBlockNode - The sync block node to update
24
+ */
25
+ updateSyncBlockData(syncBlockNode) {
26
+ if (this.isSourceBlock(syncBlockNode)) {
27
+ this.sourceSyncBlockStoreManager.updateSyncBlockData(syncBlockNode);
28
+ } else {
29
+ throw new Error('Invalid sync block node type provided for updateSyncBlockData');
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Save content of bodiedSyncBlock nodes in local cache to backend
35
+ *
36
+ * @returns true if saving all nodes successfully, false if fail to save some/all nodes
37
+ */
38
+ flushBodiedSyncBlocks() {
39
+ // only applicable to source sync block, for now (will be refactored further)
40
+ return this.sourceSyncBlockStoreManager.flushBodiedSyncBlocks();
41
+ }
42
+
43
+ /**
44
+ * Get the URL for a sync block.
45
+ * @param localId - The local ID of the sync block to get the URL for
46
+ * @returns
47
+ */
48
+ getSyncBlockURL(localId) {
49
+ // only applicable to reference sync block, for now (will be refactored further)
50
+ return this.referenceSyncBlockStoreManager.getSyncBlockURL(localId);
51
+ }
52
+ setEditorView(editorView) {
53
+ // only applicable to source sync block, for now (will be refactored further)
54
+ this.sourceSyncBlockStoreManager.setEditorView(editorView);
55
+ }
56
+ isSourceBlock(node) {
57
+ return node.type.name === 'bodiedSyncBlock';
58
+ }
59
+ registerConfirmationCallback(callback) {
60
+ // only applicable to source sync block, for now (will be refactored further)
61
+ return this.sourceSyncBlockStoreManager.registerConfirmationCallback(callback);
62
+ }
63
+ requireConfirmationBeforeDelete() {
64
+ // only applicable to source sync block, for now (will be refactored further)
65
+ return this.sourceSyncBlockStoreManager.requireConfirmationBeforeDelete();
66
+ }
67
+ createSyncBlockNode() {
68
+ // only applicable to source sync block, for now (will be refactored further)
69
+ return this.sourceSyncBlockStoreManager.createSyncBlockNode();
70
+ }
71
+ deleteSyncBlocksWithConfirmation(tr, syncBlockIds) {
72
+ // only applicable to source sync block, for now (will be refactored further)
73
+ return this.sourceSyncBlockStoreManager.deleteSyncBlocksWithConfirmation(tr, syncBlockIds);
74
+ }
75
+ rebaseTransaction(incomingTr, state) {
76
+ // only applicable to source sync block, for now (will be refactored further)
77
+ this.sourceSyncBlockStoreManager.rebaseTransaction(incomingTr, state);
78
+ }
79
+ }
@@ -1,16 +1,3 @@
1
- import { JSONTransformer } from '@atlaskit/editor-json-transformer';
2
- export const convertSyncBlockPMNodeToSyncBlockNode = (node, includeContent = false) => {
3
- const transformer = new JSONTransformer();
4
- const toJSON = node => transformer.encodeNode(node);
5
- return {
6
- type: 'syncBlock',
7
- attrs: {
8
- localId: node.attrs.localId,
9
- resourceId: node.attrs.resourceId
10
- },
11
- content: includeContent ? node.content.content.map(toJSON) : undefined
12
- };
13
- };
14
1
  export const convertSyncBlockPMNodeToSyncBlockData = node => {
15
2
  return {
16
3
  blockInstanceId: node.attrs.localId,
@@ -1,22 +1,6 @@
1
- import _createClass from "@babel/runtime/helpers/createClass";
2
- import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
- import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
4
- import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
5
- import _inherits from "@babel/runtime/helpers/inherits";
6
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
7
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
8
- import { NodeDataProvider } from '@atlaskit/node-data-provider';
9
1
  export var SyncBlockStatus = /*#__PURE__*/function (SyncBlockStatus) {
10
2
  SyncBlockStatus["Errored"] = "errored";
11
3
  SyncBlockStatus["NotFound"] = "not_found";
12
4
  SyncBlockStatus["Unauthorized"] = "unauthorized";
13
5
  return SyncBlockStatus;
14
- }({});
15
- export var SyncBlockDataProvider = /*#__PURE__*/function (_NodeDataProvider) {
16
- function SyncBlockDataProvider() {
17
- _classCallCheck(this, SyncBlockDataProvider);
18
- return _callSuper(this, SyncBlockDataProvider, arguments);
19
- }
20
- _inherits(SyncBlockDataProvider, _NodeDataProvider);
21
- return _createClass(SyncBlockDataProvider);
22
- }(NodeDataProvider);
6
+ }({});
@@ -0,0 +1,36 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ import { SyncBlockStatus } from '../common/types';
4
+ export var useFetchSyncBlockData = function useFetchSyncBlockData(manager, syncBlockNode) {
5
+ var _useState = useState(null),
6
+ _useState2 = _slicedToArray(_useState, 2),
7
+ fetchSyncBlockDataResult = _useState2[0],
8
+ setFetchSyncBlockDataResult = _useState2[1];
9
+ var fetchSyncBlockNode = useCallback(function () {
10
+ manager.fetchSyncBlockData(syncBlockNode).then(function (data) {
11
+ if (data && 'status' in data) {
12
+ // if there is an error, we don't want to replace real existing data with the error data
13
+ if (!fetchSyncBlockDataResult || 'status' in fetchSyncBlockDataResult) {
14
+ setFetchSyncBlockDataResult(data);
15
+ }
16
+ } else {
17
+ setFetchSyncBlockDataResult(data !== null && data !== void 0 ? data : null);
18
+ }
19
+ }).catch(function () {
20
+ //TODO: EDITOR-1921 - add error analytics
21
+ if (!fetchSyncBlockDataResult || 'status' in fetchSyncBlockDataResult) {
22
+ setFetchSyncBlockDataResult({
23
+ status: SyncBlockStatus.Errored
24
+ });
25
+ }
26
+ });
27
+ }, [manager, syncBlockNode, fetchSyncBlockDataResult]);
28
+ useEffect(function () {
29
+ fetchSyncBlockNode();
30
+ var interval = window.setInterval(fetchSyncBlockNode, 3000);
31
+ return function () {
32
+ window.clearInterval(interval);
33
+ };
34
+ }, [fetchSyncBlockNode]);
35
+ return fetchSyncBlockDataResult;
36
+ };
@@ -0,0 +1,7 @@
1
+ import { useEffect } from 'react';
2
+ export var useHandleContentChanges = function useHandleContentChanges(manager, syncBlockNode) {
3
+ useEffect(function () {
4
+ //TODO: EDITOR-1921 - add error analytics
5
+ manager.updateSyncBlockData(syncBlockNode);
6
+ }, [manager, syncBlockNode]);
7
+ };
package/dist/esm/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  /* eslint-disable @atlaskit/editor/no-re-export */
2
2
 
3
- export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './common/syncBlockProvider';
4
- export { SyncBlockStoreManager, useFetchSyncBlockData, useHandleContentChanges } from './common/syncBlockStoreManager';
3
+ export { SyncBlockProvider as SyncedBlockProvider, useMemoizedSyncedBlockProvider } from './providers/syncBlockProvider';
4
+ export { SyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
5
+ export { useFetchSyncBlockData } from './hooks/useFetchSyncBlockData';
6
+ export { useHandleContentChanges } from './hooks/useHandleContentChanges';
5
7
  export { SyncBlockStatus } from './common/types';
6
- export { inMemoryFetchProvider, inMemoryWriteProvider } from './providers/inMemory';
8
+ export { inMemoryFetchProvider, inMemoryWriteProvider } from './providers/in-memory/inMemory';
7
9
  export { getDefaultSyncBlockSchema } from './common/schema';
8
- export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluenceContentAPI';
10
+ export { createContentAPIProvidersWithDefaultKey, useMemoizedContentAPIProviders } from './providers/confluence/confluenceContentAPI';
9
11
  export { getConfluencePageAri } from './utils/ari';
10
- export { convertSyncBlockPMNodeToSyncBlockNode as convertSyncBlockPMNodeToSyncBlockData } from './utils/utils';
12
+ export { convertSyncBlockPMNodeToSyncBlockData } from './utils/utils';
11
13
  export { rebaseTransaction } from './common/rebase-transaction';
@@ -5,10 +5,10 @@ import _createClass from "@babel/runtime/helpers/createClass";
5
5
  import _typeof from "@babel/runtime/helpers/typeof";
6
6
  import _regeneratorRuntime from "@babel/runtime/regenerator";
7
7
  import { useMemo } from 'react';
8
- import { SyncBlockStatus } from '../common/types';
9
- import { getLocalIdFromAri, getPageIdAndTypeFromAri } from '../utils/ari';
10
- import { getContentProperty, createContentProperty, updateContentProperty } from '../utils/contentProperty';
11
- import { isBlogPageType } from '../utils/utils';
8
+ import { SyncBlockStatus } from '../../common/types';
9
+ import { getLocalIdFromAri, getPageIdAndTypeFromAri } from '../../utils/ari';
10
+ import { getContentProperty, createContentProperty, updateContentProperty } from '../../utils/contentProperty';
11
+ import { isBlogPageType } from '../../utils/utils';
12
12
 
13
13
  /**
14
14
  * Configuration for Content API providers
@@ -9,8 +9,8 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
9
9
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
10
10
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
11
11
  import { useMemo } from 'react';
12
+ import { SyncBlockDataProvider } from '../providers/types';
12
13
  import { getLocalIdFromAri, getPageARIFromResourceId } from '../utils/ari';
13
- import { SyncBlockDataProvider } from './types';
14
14
  export var SyncBlockProvider = /*#__PURE__*/function (_SyncBlockDataProvide) {
15
15
  function SyncBlockProvider(fetchProvider, writeProvider, sourceId) {
16
16
  var _this;
@@ -0,0 +1,16 @@
1
+ import _createClass from "@babel/runtime/helpers/createClass";
2
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
4
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
5
+ import _inherits from "@babel/runtime/helpers/inherits";
6
+ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
7
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
8
+ import { NodeDataProvider } from '@atlaskit/node-data-provider';
9
+ export var SyncBlockDataProvider = /*#__PURE__*/function (_NodeDataProvider) {
10
+ function SyncBlockDataProvider() {
11
+ _classCallCheck(this, SyncBlockDataProvider);
12
+ return _callSuper(this, SyncBlockDataProvider, arguments);
13
+ }
14
+ _inherits(SyncBlockDataProvider, _NodeDataProvider);
15
+ return _createClass(SyncBlockDataProvider);
16
+ }(NodeDataProvider);
@@ -0,0 +1,116 @@
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
+ 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; }
7
+ 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; }
8
+ var createSyncBlockNode = function createSyncBlockNode(localId, resourceId) {
9
+ return {
10
+ type: 'syncBlock',
11
+ attrs: {
12
+ localId: localId,
13
+ resourceId: resourceId
14
+ }
15
+ };
16
+ };
17
+ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
18
+ function ReferenceSyncBlockStoreManager(dataProvider) {
19
+ _classCallCheck(this, ReferenceSyncBlockStoreManager);
20
+ this.dataProvider = dataProvider;
21
+ this.syncBlockCache = new Map();
22
+ this.syncBlockURLRequests = new Map();
23
+ }
24
+
25
+ /**
26
+ *
27
+ * @param localId - The local ID of the sync block to get the source URL for
28
+ * @param resourceId - The resource ID of the sync block to get the source URL for
29
+ * Fetches source URl for a sync block and updates sync block data with the source URL asynchronously.
30
+ */
31
+ return _createClass(ReferenceSyncBlockStoreManager, [{
32
+ key: "fetchSyncBlockSourceURL",
33
+ value: function fetchSyncBlockSourceURL(_ref) {
34
+ var _this = this;
35
+ var localId = _ref.localId,
36
+ resourceId = _ref.resourceId;
37
+ if (!localId || !resourceId || !this.dataProvider) {
38
+ return;
39
+ }
40
+
41
+ // if the sync block is a reference block, we need to fetch the URL to the source
42
+ // we could optimise this further by checking if the sync block is on the same page as the source
43
+ if (!this.syncBlockURLRequests.get(localId)) {
44
+ this.syncBlockURLRequests.set(localId, true);
45
+ this.dataProvider.retrieveSyncBlockSourceUrl(createSyncBlockNode(localId, resourceId)).then(function (sourceURL) {
46
+ var existingSyncBlock = _this.syncBlockCache.get(localId);
47
+ if (existingSyncBlock) {
48
+ existingSyncBlock.sourceURL = sourceURL;
49
+ }
50
+ }).finally(function () {
51
+ _this.syncBlockURLRequests.set(localId, false);
52
+ });
53
+ }
54
+ }
55
+ }, {
56
+ key: "fetchSyncBlockData",
57
+ value: function () {
58
+ var _fetchSyncBlockData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(syncBlockNode) {
59
+ var syncNode, existingSyncBlock, data, fetchSyncBlockDataResult;
60
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
61
+ while (1) switch (_context.prev = _context.next) {
62
+ case 0:
63
+ if (this.dataProvider) {
64
+ _context.next = 2;
65
+ break;
66
+ }
67
+ throw new Error('Data provider not set');
68
+ case 2:
69
+ syncNode = createSyncBlockNode(syncBlockNode.attrs.localId, syncBlockNode.attrs.resourceId); // async fetch source URL if it is not already fetched
70
+ existingSyncBlock = this.syncBlockCache.get(syncBlockNode.attrs.localId);
71
+ if (!(existingSyncBlock !== null && existingSyncBlock !== void 0 && existingSyncBlock.sourceURL)) {
72
+ this.fetchSyncBlockSourceURL({
73
+ localId: syncBlockNode.attrs.localId,
74
+ resourceId: syncBlockNode.attrs.resourceId
75
+ });
76
+ }
77
+ _context.next = 7;
78
+ return this.dataProvider.fetchNodesData([syncNode]);
79
+ case 7:
80
+ data = _context.sent;
81
+ if (data) {
82
+ _context.next = 10;
83
+ break;
84
+ }
85
+ throw new Error('Failed to fetch sync block node data');
86
+ case 10:
87
+ fetchSyncBlockDataResult = data[0];
88
+ if (!('status' in fetchSyncBlockDataResult)) {
89
+ // only adds it to the map if it did not error out
90
+ this.syncBlockCache.set(syncBlockNode.attrs.localId, _objectSpread(_objectSpread({}, existingSyncBlock), fetchSyncBlockDataResult));
91
+ }
92
+ return _context.abrupt("return", fetchSyncBlockDataResult);
93
+ case 13:
94
+ case "end":
95
+ return _context.stop();
96
+ }
97
+ }, _callee, this);
98
+ }));
99
+ function fetchSyncBlockData(_x) {
100
+ return _fetchSyncBlockData.apply(this, arguments);
101
+ }
102
+ return fetchSyncBlockData;
103
+ }()
104
+ /**
105
+ * Get the URL for a sync block.
106
+ * @param localId - The local ID of the sync block to get the URL for
107
+ * @returns
108
+ */
109
+ }, {
110
+ key: "getSyncBlockURL",
111
+ value: function getSyncBlockURL(localId) {
112
+ var syncBlock = this.syncBlockCache.get(localId);
113
+ return syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.sourceURL;
114
+ }
115
+ }]);
116
+ }();