@atlaskit/editor-synced-block-provider 3.30.3 → 3.30.4

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 (37) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/clients/block-service/blockSubscription.js +3 -53
  3. package/dist/cjs/clients/block-service/sharedSubscriptionUtils.js +82 -0
  4. package/dist/cjs/index.js +33 -0
  5. package/dist/cjs/providers/block-service/blockServiceAPI.js +22 -6
  6. package/dist/cjs/utils/__generated__/relaySubscriptionUtilsSubscription.graphql.js +94 -0
  7. package/dist/cjs/utils/relayResponseConverter.js +76 -0
  8. package/dist/cjs/utils/relaySubscriptionUtils.js +130 -0
  9. package/dist/es2019/clients/block-service/blockSubscription.js +2 -67
  10. package/dist/es2019/clients/block-service/sharedSubscriptionUtils.js +91 -0
  11. package/dist/es2019/index.js +4 -0
  12. package/dist/es2019/providers/block-service/blockServiceAPI.js +22 -6
  13. package/dist/es2019/utils/__generated__/relaySubscriptionUtilsSubscription.graphql.js +88 -0
  14. package/dist/es2019/utils/relayResponseConverter.js +69 -0
  15. package/dist/es2019/utils/relaySubscriptionUtils.js +125 -0
  16. package/dist/esm/clients/block-service/blockSubscription.js +2 -52
  17. package/dist/esm/clients/block-service/sharedSubscriptionUtils.js +76 -0
  18. package/dist/esm/index.js +4 -0
  19. package/dist/esm/providers/block-service/blockServiceAPI.js +22 -6
  20. package/dist/esm/utils/__generated__/relaySubscriptionUtilsSubscription.graphql.js +88 -0
  21. package/dist/esm/utils/relayResponseConverter.js +69 -0
  22. package/dist/esm/utils/relaySubscriptionUtils.js +123 -0
  23. package/dist/types/clients/block-service/blockSubscription.d.ts +1 -26
  24. package/dist/types/clients/block-service/sharedSubscriptionUtils.d.ts +61 -0
  25. package/dist/types/index.d.ts +4 -0
  26. package/dist/types/providers/block-service/blockServiceAPI.d.ts +7 -2
  27. package/dist/types/utils/__generated__/relaySubscriptionUtilsSubscription.graphql.d.ts +31 -0
  28. package/dist/types/utils/relayResponseConverter.d.ts +47 -0
  29. package/dist/types/utils/relaySubscriptionUtils.d.ts +61 -0
  30. package/dist/types-ts4.5/clients/block-service/blockSubscription.d.ts +1 -26
  31. package/dist/types-ts4.5/clients/block-service/sharedSubscriptionUtils.d.ts +61 -0
  32. package/dist/types-ts4.5/index.d.ts +4 -0
  33. package/dist/types-ts4.5/providers/block-service/blockServiceAPI.d.ts +7 -2
  34. package/dist/types-ts4.5/utils/__generated__/relaySubscriptionUtilsSubscription.graphql.d.ts +31 -0
  35. package/dist/types-ts4.5/utils/relayResponseConverter.d.ts +47 -0
  36. package/dist/types-ts4.5/utils/relaySubscriptionUtils.d.ts +61 -0
  37. package/package.json +3 -2
@@ -0,0 +1,76 @@
1
+ import { convertContentUpdatedAt } from '../../utils/utils';
2
+ /**
3
+ * Shared GraphQL subscription query for block updates.
4
+ * This is the canonical subscription query used across all implementations.
5
+ */
6
+ export var BLOCK_SERVICE_SUBSCRIPTION_QUERY = "\nsubscription EDITOR_SYNCED_BLOCK_ON_BLOCK_UPDATED($resourceId: ID!) {\n\tblockService_onBlockUpdated(resourceId: $resourceId) {\n\t\tblockAri\n\t\tblockInstanceId\n\t\tcontent\n\t\tcontentUpdatedAt\n\t\tcreatedAt\n\t\tcreatedBy\n\t\tdeletionReason\n\t\tproduct\n\t\tsourceAri\n\t\tstatus\n\t}\n}\n";
7
+
8
+ /**
9
+ * Raw subscription payload from the GraphQL subscription.
10
+ * This represents the exact shape returned by the blockService_onBlockUpdated subscription.
11
+ */
12
+
13
+ /**
14
+ * Parsed and normalized block subscription data.
15
+ * This is the standardized format used across different subscription implementations.
16
+ */
17
+
18
+ /**
19
+ * Extracts the resourceId from a block ARI.
20
+ * Block ARI format: ari:cloud:blocks:<cloudId>:synced-block/<resourceId>
21
+ * @param blockAri - The block ARI string
22
+ * @returns The resourceId portion of the ARI
23
+ */
24
+ export var extractResourceIdFromBlockAri = function extractResourceIdFromBlockAri(blockAri) {
25
+ // eslint-disable-next-line require-unicode-regexp
26
+ var match = blockAri.match(/ari:cloud:blocks:[^:]+:synced-block\/(.+)$/);
27
+ return (match === null || match === void 0 ? void 0 : match[1]) || null;
28
+ };
29
+
30
+ /**
31
+ * Converts a timestamp to ISO string.
32
+ * @param timestamp - Timestamp in milliseconds
33
+ * @returns ISO string or undefined if conversion fails
34
+ */
35
+ export var convertTimestampToISOString = function convertTimestampToISOString(timestamp) {
36
+ if (timestamp === undefined || timestamp === null) {
37
+ return undefined;
38
+ }
39
+ try {
40
+ return new Date(timestamp).toISOString();
41
+ } catch (_unused) {
42
+ return undefined;
43
+ }
44
+ };
45
+
46
+ /**
47
+ * Parses the raw subscription payload into a standardized format.
48
+ * This function handles all the data transformation and error handling consistently
49
+ * across different subscription implementations.
50
+ *
51
+ * @param payload - The raw subscription payload
52
+ * @returns Parsed block data or null if parsing fails
53
+ */
54
+ export var parseSubscriptionPayload = function parseSubscriptionPayload(payload) {
55
+ try {
56
+ var resourceId = extractResourceIdFromBlockAri(payload.blockAri);
57
+ if (!resourceId) {
58
+ return null;
59
+ }
60
+ var createdAt = convertTimestampToISOString(payload.createdAt);
61
+ return {
62
+ blockAri: payload.blockAri,
63
+ blockInstanceId: payload.blockInstanceId,
64
+ content: JSON.parse(payload.content),
65
+ contentUpdatedAt: convertContentUpdatedAt(payload.contentUpdatedAt),
66
+ createdAt: createdAt,
67
+ createdBy: payload.createdBy,
68
+ product: payload.product,
69
+ resourceId: resourceId,
70
+ sourceAri: payload.sourceAri,
71
+ status: payload.status
72
+ };
73
+ } catch (_unused2) {
74
+ return null;
75
+ }
76
+ };
package/dist/esm/index.js CHANGED
@@ -25,6 +25,10 @@ export { SyncBlockInMemorySessionCache, syncBlockInMemorySessionCache } from './
25
25
  export { SyncBlockStoreManager, useMemoizedSyncBlockStoreManager } from './store-manager/syncBlockStoreManager';
26
26
 
27
27
  // utils
28
+ export { BLOCK_SERVICE_SUBSCRIPTION_QUERY } from './clients/block-service/sharedSubscriptionUtils';
29
+ export { parseSubscriptionPayload } from './clients/block-service/sharedSubscriptionUtils';
30
+ export { convertRelayResponseToSyncBlockInstance } from './utils/relayResponseConverter';
31
+ export { createRelayBlockSubscription, createRelaySubscriptionFunction } from './utils/relaySubscriptionUtils';
28
32
  export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
29
33
  export { parseResourceId, createResourceIdForReference } from './utils/resourceId';
30
34
  export { createSyncBlockNode, convertSyncBlockPMNodeToSyncBlockData, convertSyncBlockJSONNodeToSyncBlockNode, convertPMNodesToSyncBlockNodes, getContentIdAndProductFromResourceId } from './utils/utils';
@@ -17,6 +17,7 @@ import { batchRetrieveSyncedBlocks, BlockError, createSyncedBlock, deleteSyncedB
17
17
  import { subscribeToBlockUpdates as subscribeToBlockUpdatesWS } from '../../clients/block-service/blockSubscription';
18
18
  import { SyncBlockError } from '../../common/types';
19
19
  import { stringifyError } from '../../utils/errorHandling';
20
+ import { createRelaySubscriptionFunction } from '../../utils/relaySubscriptionUtils';
20
21
  import { createResourceIdForReference } from '../../utils/resourceId';
21
22
  import { convertContentUpdatedAt } from '../../utils/utils';
22
23
  var mapBlockError = function mapBlockError(error) {
@@ -422,10 +423,12 @@ export { _batchFetchData as batchFetchData };
422
423
  var BlockServiceADFFetchProvider = /*#__PURE__*/function () {
423
424
  function BlockServiceADFFetchProvider(_ref4) {
424
425
  var cloudId = _ref4.cloudId,
425
- parentAri = _ref4.parentAri;
426
+ parentAri = _ref4.parentAri,
427
+ relayEnvironment = _ref4.relayEnvironment;
426
428
  _classCallCheck(this, BlockServiceADFFetchProvider);
427
429
  this.cloudId = cloudId;
428
430
  this.parentAri = parentAri;
431
+ this.relayEnvironment = relayEnvironment;
429
432
  }
430
433
 
431
434
  // resourceId of the reference synced block.
@@ -610,6 +613,7 @@ var BlockServiceADFFetchProvider = /*#__PURE__*/function () {
610
613
  }()
611
614
  /**
612
615
  * Subscribes to real-time updates for a specific block using GraphQL WebSocket subscriptions.
616
+ * If a Relay environment is provided, uses Relay subscriptions; otherwise falls back to WebSocket.
613
617
  * @param resourceId - The resource ID of the block to subscribe to
614
618
  * @param onUpdate - Callback function invoked when the block is updated
615
619
  * @param onError - Optional callback function invoked on subscription errors
@@ -623,6 +627,14 @@ var BlockServiceADFFetchProvider = /*#__PURE__*/function () {
623
627
  cloudId: this.cloudId,
624
628
  resourceId: resourceId
625
629
  });
630
+
631
+ // If Relay environment is available, use Relay subscriptions
632
+ if (this.relayEnvironment && fg('platform_synced_block_patch_3')) {
633
+ var relaySubscribeToBlockUpdates = createRelaySubscriptionFunction(this.cloudId, this.relayEnvironment);
634
+ return relaySubscribeToBlockUpdates(resourceId, onUpdate, onError);
635
+ }
636
+
637
+ // Fall back to WebSocket subscriptions
626
638
  return subscribeToBlockUpdatesWS(blockAri, function (parsedData) {
627
639
  // Convert ParsedBlockSubscriptionData to SyncBlockInstance
628
640
  var syncBlockInstance = {
@@ -974,11 +986,13 @@ var createBlockServiceAPIProviders = function createBlockServiceAPIProviders(_re
974
986
  parentAri = _ref6.parentAri,
975
987
  parentId = _ref6.parentId,
976
988
  product = _ref6.product,
977
- getVersion = _ref6.getVersion;
989
+ getVersion = _ref6.getVersion,
990
+ relayEnvironment = _ref6.relayEnvironment;
978
991
  return {
979
992
  fetchProvider: new BlockServiceADFFetchProvider({
980
993
  cloudId: cloudId,
981
- parentAri: parentAri
994
+ parentAri: parentAri,
995
+ relayEnvironment: relayEnvironment
982
996
  }),
983
997
  writeProvider: new BlockServiceADFWriteProvider({
984
998
  cloudId: cloudId,
@@ -994,16 +1008,18 @@ export var useMemoizedBlockServiceAPIProviders = function useMemoizedBlockServic
994
1008
  parentAri = _ref7.parentAri,
995
1009
  parentId = _ref7.parentId,
996
1010
  product = _ref7.product,
997
- getVersion = _ref7.getVersion;
1011
+ getVersion = _ref7.getVersion,
1012
+ relayEnvironment = _ref7.relayEnvironment;
998
1013
  return useMemo(function () {
999
1014
  return createBlockServiceAPIProviders({
1000
1015
  cloudId: cloudId,
1001
1016
  parentAri: parentAri,
1002
1017
  parentId: parentId,
1003
1018
  product: product,
1004
- getVersion: getVersion
1019
+ getVersion: getVersion,
1020
+ relayEnvironment: relayEnvironment
1005
1021
  });
1006
- }, [cloudId, parentAri, parentId, product, getVersion]);
1022
+ }, [cloudId, parentAri, parentId, product, getVersion, relayEnvironment]);
1007
1023
  };
1008
1024
  var createBlockServiceFetchOnlyAPIProvider = function createBlockServiceFetchOnlyAPIProvider(_ref8) {
1009
1025
  var cloudId = _ref8.cloudId,
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @generated SignedSource<<559b4fb25d0e5bc72be383427a939e2d>>
3
+ * @relayHash 38684212c43376e58fea2d6095011652
4
+ * @lightSyntaxTransform
5
+ * @nogrep
6
+ * @codegen-command: yarn relay
7
+ */
8
+
9
+ /* tslint:disable */
10
+ /* eslint-disable */
11
+ // @ts-nocheck
12
+
13
+ // @relayRequestID c84045a1f05bd1e73ade0a9d8b18462cc3dad5dcae1ebabab76b13135411c530
14
+
15
+ var node = function () {
16
+ var v0 = [{
17
+ "defaultValue": null,
18
+ "kind": "LocalArgument",
19
+ "name": "resourceId"
20
+ }],
21
+ v1 = [{
22
+ "args": [{
23
+ "kind": "Variable",
24
+ "name": "resourceId",
25
+ "variableName": "resourceId"
26
+ }],
27
+ "concreteType": "BlockServiceBlockPayload",
28
+ "kind": "LinkedField",
29
+ "name": "blockService_onBlockUpdated",
30
+ "plural": false,
31
+ "selections": [{
32
+ "kind": "ScalarField",
33
+ "name": "blockAri"
34
+ }, {
35
+ "kind": "ScalarField",
36
+ "name": "blockInstanceId"
37
+ }, {
38
+ "kind": "ScalarField",
39
+ "name": "content"
40
+ }, {
41
+ "kind": "ScalarField",
42
+ "name": "contentUpdatedAt"
43
+ }, {
44
+ "kind": "ScalarField",
45
+ "name": "createdAt"
46
+ }, {
47
+ "kind": "ScalarField",
48
+ "name": "createdBy"
49
+ }, {
50
+ "kind": "ScalarField",
51
+ "name": "deletionReason"
52
+ }, {
53
+ "kind": "ScalarField",
54
+ "name": "product"
55
+ }, {
56
+ "kind": "ScalarField",
57
+ "name": "sourceAri"
58
+ }, {
59
+ "kind": "ScalarField",
60
+ "name": "status"
61
+ }]
62
+ }];
63
+ return {
64
+ "fragment": {
65
+ "argumentDefinitions": v0 /*: any*/,
66
+ "kind": "Fragment",
67
+ "name": "relaySubscriptionUtilsSubscription",
68
+ "selections": v1 /*: any*/,
69
+ "type": "Subscription"
70
+ },
71
+ "kind": "Request",
72
+ "operation": {
73
+ "argumentDefinitions": v0 /*: any*/,
74
+ "kind": "Operation",
75
+ "name": "relaySubscriptionUtilsSubscription",
76
+ "selections": v1 /*: any*/
77
+ },
78
+ "params": {
79
+ "id": "c84045a1f05bd1e73ade0a9d8b18462cc3dad5dcae1ebabab76b13135411c530",
80
+ "metadata": {},
81
+ "name": "relaySubscriptionUtilsSubscription",
82
+ "operationKind": "subscription",
83
+ "text": null
84
+ }
85
+ };
86
+ }();
87
+ node.hash = "6f3ebc87921555436cad753ec1aead2e";
88
+ export default node;
@@ -0,0 +1,69 @@
1
+ import { parseSubscriptionPayload } from '../clients/block-service/sharedSubscriptionUtils';
2
+ import { normaliseSyncBlockStatus } from './validValue';
3
+ /**
4
+ * Converts parsed subscription data to SyncBlockInstance format.
5
+ *
6
+ * @param parsed - The parsed subscription data
7
+ * @param resourceId - The resource ID for the block
8
+ * @returns A SyncBlockInstance
9
+ */
10
+ export function convertParsedDataToSyncBlockInstance(parsed, resourceId) {
11
+ return {
12
+ data: {
13
+ content: parsed.content,
14
+ contentUpdatedAt: parsed.contentUpdatedAt,
15
+ resourceId: parsed.blockAri,
16
+ blockInstanceId: parsed.blockInstanceId,
17
+ sourceAri: parsed.sourceAri,
18
+ product: parsed.product,
19
+ createdAt: parsed.createdAt,
20
+ createdBy: parsed.createdBy,
21
+ status: normaliseSyncBlockStatus(parsed.status)
22
+ },
23
+ resourceId: resourceId
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Converts a Relay subscription response to SyncBlockInstance format using shared parsing logic.
29
+
30
+ * @param response - The Relay subscription response containing block update data
31
+ * @param resourceId - The resource ID for the block
32
+ * @returns A SyncBlockInstance or null if parsing fails
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // In a Relay subscription handler
37
+ * onNext: (response) => {
38
+ * if (response?.blockService_onBlockUpdated) {
39
+ * const syncBlockInstance = convertRelayResponseToSyncBlockInstance(
40
+ * response.blockService_onBlockUpdated,
41
+ * resourceId,
42
+ * );
43
+ * if (syncBlockInstance) {
44
+ * onUpdate(syncBlockInstance);
45
+ * }
46
+ * }
47
+ * }
48
+ * ```
49
+ */
50
+ export function convertRelayResponseToSyncBlockInstance(response, resourceId) {
51
+ var _response$contentUpda, _response$deletionRea;
52
+ var payload = {
53
+ blockAri: response.blockAri,
54
+ blockInstanceId: response.blockInstanceId,
55
+ content: response.content,
56
+ contentUpdatedAt: (_response$contentUpda = response.contentUpdatedAt) !== null && _response$contentUpda !== void 0 ? _response$contentUpda : undefined,
57
+ createdAt: response.createdAt,
58
+ createdBy: response.createdBy,
59
+ deletionReason: (_response$deletionRea = response.deletionReason) !== null && _response$deletionRea !== void 0 ? _response$deletionRea : undefined,
60
+ product: response.product,
61
+ sourceAri: response.sourceAri,
62
+ status: response.status
63
+ };
64
+ var parsed = parseSubscriptionPayload(payload);
65
+ if (!parsed) {
66
+ return null;
67
+ }
68
+ return convertParsedDataToSyncBlockInstance(parsed, resourceId);
69
+ }
@@ -0,0 +1,123 @@
1
+ import { requestSubscription } from 'relay-runtime';
2
+ import { generateBlockAriFromReference } from '../clients/block-service/ari';
3
+ import { subscribeToBlockUpdates as subscribeToBlockUpdatesWS } from '../clients/block-service/blockSubscription';
4
+ import relaySubscriptionUtilsSubscriptionDocument from './__generated__/relaySubscriptionUtilsSubscription.graphql';
5
+ import { convertRelayResponseToSyncBlockInstance, convertParsedDataToSyncBlockInstance } from './relayResponseConverter';
6
+
7
+ /**
8
+ * Configuration for creating a Relay block subscription.
9
+ */
10
+
11
+ /**
12
+ * Creates a Relay-based block subscription without needing to wrap providers.
13
+ * This is a clean utility function that can be used directly in components or hooks.
14
+ *
15
+ * @param config - Configuration for the subscription
16
+ * @returns An unsubscribe function to dispose the subscription
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const unsubscribe = createRelayBlockSubscription({
21
+ * relayEnvironment: environment,
22
+ * cloudId: 'my-cloud-id',
23
+ * resourceId: 'my-resource-id',
24
+ * onUpdate: (blockInstance) => {
25
+ * console.log('Block updated:', blockInstance);
26
+ * },
27
+ * onError: (error) => {
28
+ * console.error('Subscription error:', error);
29
+ * }
30
+ * });
31
+ *
32
+ * // Later, when component unmounts or subscription is no longer needed
33
+ * unsubscribe();
34
+ * ```
35
+ */
36
+ export function createRelayBlockSubscription(config) {
37
+ var relayEnvironment = config.relayEnvironment,
38
+ cloudId = config.cloudId,
39
+ resourceId = config.resourceId,
40
+ onUpdate = config.onUpdate,
41
+ _onError = config.onError;
42
+
43
+ // Convert resourceId to blockAri for the subscription
44
+ var blockAri = generateBlockAriFromReference({
45
+ cloudId: cloudId,
46
+ resourceId: resourceId
47
+ });
48
+ var subscriptionQuery = relaySubscriptionUtilsSubscriptionDocument;
49
+
50
+ // Try to use Relay subscription first
51
+ try {
52
+ var disposable = requestSubscription(relayEnvironment, {
53
+ subscription: subscriptionQuery,
54
+ variables: {
55
+ resourceId: blockAri
56
+ },
57
+ onNext: function onNext(response) {
58
+ if (response !== null && response !== void 0 && response.blockService_onBlockUpdated) {
59
+ var syncBlockInstance = convertRelayResponseToSyncBlockInstance(response.blockService_onBlockUpdated, resourceId);
60
+ if (syncBlockInstance) {
61
+ onUpdate(syncBlockInstance);
62
+ } else {
63
+ _onError === null || _onError === void 0 || _onError(new Error('Failed to parse Relay block subscription payload'));
64
+ }
65
+ }
66
+ },
67
+ onError: function onError(error) {
68
+ _onError === null || _onError === void 0 || _onError(error);
69
+ }
70
+ });
71
+
72
+ // If subscription was successfully created, return the unsubscribe function
73
+ if (disposable) {
74
+ return function () {
75
+ disposable.dispose();
76
+ };
77
+ }
78
+ } catch (error) {
79
+ // If requestSubscription throws, fall back to WebSocket
80
+ _onError === null || _onError === void 0 || _onError(error instanceof Error ? error : new Error('Relay subscription failed'));
81
+ }
82
+
83
+ // Fallback to WebSocket subscription when Relay subscriptions aren't available
84
+ return subscribeToBlockUpdatesWS(blockAri, function (parsedData) {
85
+ var syncBlockInstance = convertParsedDataToSyncBlockInstance(parsedData, parsedData.resourceId);
86
+ onUpdate(syncBlockInstance);
87
+ }, function (error) {
88
+ _onError === null || _onError === void 0 || _onError(error);
89
+ });
90
+ }
91
+
92
+ /**
93
+ * Hook-like function to create a subscription function that can be passed to providers.
94
+ * This creates a function with the same signature as subscribeToBlockUpdates that uses Relay.
95
+ *
96
+ * @param cloudId - Cloud ID for generating block ARIs
97
+ * @param relayEnvironment - Optional Relay environment. If not provided, will attempt to use global environment
98
+ * @returns A function that can be used as subscribeToBlockUpdates in provider configurations
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * const relaySubscribeToBlockUpdates = createRelaySubscriptionFunction(cloudId, environment);
103
+ *
104
+ * // Can be used directly as a subscribeToBlockUpdates replacement
105
+ * const unsubscribe = relaySubscribeToBlockUpdates(resourceId, onUpdate, onError);
106
+ * ```
107
+ */
108
+ export function createRelaySubscriptionFunction(cloudId, relayEnvironment) {
109
+ return function (resourceId, onUpdate, onError) {
110
+ var environment = relayEnvironment;
111
+ if (!environment) {
112
+ onError === null || onError === void 0 || onError(new Error('Relay environment not available'));
113
+ return function () {};
114
+ }
115
+ return createRelayBlockSubscription({
116
+ relayEnvironment: environment,
117
+ cloudId: cloudId,
118
+ resourceId: resourceId,
119
+ onUpdate: onUpdate,
120
+ onError: onError
121
+ });
122
+ };
123
+ }
@@ -1,29 +1,4 @@
1
- import type { ADFEntity } from '@atlaskit/adf-utils/types';
2
- import type { SyncBlockProduct } from '../../common/types';
3
- export type BlockSubscriptionPayload = {
4
- blockAri: string;
5
- blockInstanceId: string;
6
- content: string;
7
- contentUpdatedAt?: number;
8
- createdAt: number;
9
- createdBy: string;
10
- deletionReason?: string;
11
- product: string;
12
- sourceAri: string;
13
- status: string;
14
- };
15
- export type ParsedBlockSubscriptionData = {
16
- blockAri: string;
17
- blockInstanceId: string;
18
- content: ADFEntity[];
19
- contentUpdatedAt?: string;
20
- createdAt?: string;
21
- createdBy: string;
22
- product: SyncBlockProduct;
23
- resourceId: string;
24
- sourceAri: string;
25
- status: string;
26
- };
1
+ import { type ParsedBlockSubscriptionData } from './sharedSubscriptionUtils';
27
2
  type SubscriptionCallback = (data: ParsedBlockSubscriptionData) => void;
28
3
  type ErrorCallback = (error: Error) => void;
29
4
  type Unsubscribe = () => void;
@@ -0,0 +1,61 @@
1
+ import type { ADFEntity } from '@atlaskit/adf-utils/types';
2
+ import type { SyncBlockProduct } from '../../common/types';
3
+ /**
4
+ * Shared GraphQL subscription query for block updates.
5
+ * This is the canonical subscription query used across all implementations.
6
+ */
7
+ export declare const BLOCK_SERVICE_SUBSCRIPTION_QUERY = "\nsubscription EDITOR_SYNCED_BLOCK_ON_BLOCK_UPDATED($resourceId: ID!) {\n\tblockService_onBlockUpdated(resourceId: $resourceId) {\n\t\tblockAri\n\t\tblockInstanceId\n\t\tcontent\n\t\tcontentUpdatedAt\n\t\tcreatedAt\n\t\tcreatedBy\n\t\tdeletionReason\n\t\tproduct\n\t\tsourceAri\n\t\tstatus\n\t}\n}\n";
8
+ /**
9
+ * Raw subscription payload from the GraphQL subscription.
10
+ * This represents the exact shape returned by the blockService_onBlockUpdated subscription.
11
+ */
12
+ export type BlockSubscriptionPayload = {
13
+ blockAri: string;
14
+ blockInstanceId: string;
15
+ content: string;
16
+ contentUpdatedAt?: number;
17
+ createdAt: number;
18
+ createdBy: string;
19
+ deletionReason?: string;
20
+ product: string;
21
+ sourceAri: string;
22
+ status: string;
23
+ };
24
+ /**
25
+ * Parsed and normalized block subscription data.
26
+ * This is the standardized format used across different subscription implementations.
27
+ */
28
+ export type ParsedBlockSubscriptionData = {
29
+ blockAri: string;
30
+ blockInstanceId: string;
31
+ content: ADFEntity[];
32
+ contentUpdatedAt?: string;
33
+ createdAt?: string;
34
+ createdBy: string;
35
+ product: SyncBlockProduct;
36
+ resourceId: string;
37
+ sourceAri: string;
38
+ status: string;
39
+ };
40
+ /**
41
+ * Extracts the resourceId from a block ARI.
42
+ * Block ARI format: ari:cloud:blocks:<cloudId>:synced-block/<resourceId>
43
+ * @param blockAri - The block ARI string
44
+ * @returns The resourceId portion of the ARI
45
+ */
46
+ export declare const extractResourceIdFromBlockAri: (blockAri: string) => string | null;
47
+ /**
48
+ * Converts a timestamp to ISO string.
49
+ * @param timestamp - Timestamp in milliseconds
50
+ * @returns ISO string or undefined if conversion fails
51
+ */
52
+ export declare const convertTimestampToISOString: (timestamp?: number) => string | undefined;
53
+ /**
54
+ * Parses the raw subscription payload into a standardized format.
55
+ * This function handles all the data transformation and error handling consistently
56
+ * across different subscription implementations.
57
+ *
58
+ * @param payload - The raw subscription payload
59
+ * @returns Parsed block data or null if parsing fails
60
+ */
61
+ export declare const parseSubscriptionPayload: (payload: BlockSubscriptionPayload) => ParsedBlockSubscriptionData | null;
@@ -17,6 +17,10 @@ export type { ADFFetchProvider, ADFWriteProvider, BlockNodeIdentifiers, BlockSub
17
17
  export { ReferenceSyncBlockStoreManager } from './store-manager/referenceSyncBlockStoreManager';
18
18
  export { SyncBlockInMemorySessionCache, syncBlockInMemorySessionCache, } from './store-manager/syncBlockInMemorySessionCache';
19
19
  export { SyncBlockStoreManager, useMemoizedSyncBlockStoreManager, } from './store-manager/syncBlockStoreManager';
20
+ export { BLOCK_SERVICE_SUBSCRIPTION_QUERY } from './clients/block-service/sharedSubscriptionUtils';
21
+ export { type BlockSubscriptionPayload, parseSubscriptionPayload } from './clients/block-service/sharedSubscriptionUtils';
22
+ export { convertRelayResponseToSyncBlockInstance, type RelayBlockUpdateResponse } from './utils/relayResponseConverter';
23
+ export { createRelayBlockSubscription, createRelaySubscriptionFunction, type RelayBlockSubscriptionConfig } from './utils/relaySubscriptionUtils';
20
24
  export { resolveSyncBlockInstance } from './utils/resolveSyncBlockInstance';
21
25
  export { parseResourceId, createResourceIdForReference } from './utils/resourceId';
22
26
  export { createSyncBlockNode, convertSyncBlockPMNodeToSyncBlockData, convertSyncBlockJSONNodeToSyncBlockNode, convertPMNodesToSyncBlockNodes, getContentIdAndProductFromResourceId, } from './utils/utils';
@@ -1,3 +1,4 @@
1
+ import type { IEnvironment } from 'relay-runtime';
1
2
  import { type BlockContentResponse } from '../../clients/block-service/blockService';
2
3
  import { SyncBlockError, type ReferenceSyncBlockData, type ResourceId, type SyncBlockAttrs, type SyncBlockData, type SyncBlockProduct } from '../../common/types';
3
4
  import type { ADFFetchProvider, ADFWriteProvider, BlockNodeIdentifiers, DeleteSyncBlockResult, SyncBlockInstance, UpdateReferenceSyncBlockResult, WriteSyncBlockResult } from '../types';
@@ -36,6 +37,7 @@ export declare const batchFetchData: (cloudId: string, parentAri: string | undef
36
37
  interface BlockServiceADFFetchProviderProps {
37
38
  cloudId: string;
38
39
  parentAri: string | undefined;
40
+ relayEnvironment?: IEnvironment;
39
41
  }
40
42
  /**
41
43
  * ADFFetchProvider implementation that fetches synced block data from Block Service API
@@ -43,7 +45,8 @@ interface BlockServiceADFFetchProviderProps {
43
45
  declare class BlockServiceADFFetchProvider implements ADFFetchProvider {
44
46
  private cloudId;
45
47
  private parentAri;
46
- constructor({ cloudId, parentAri }: BlockServiceADFFetchProviderProps);
48
+ private relayEnvironment?;
49
+ constructor({ cloudId, parentAri, relayEnvironment }: BlockServiceADFFetchProviderProps);
47
50
  fetchData(resourceId: string): Promise<SyncBlockInstance>;
48
51
  fetchReferences(referenceResourceId: string): Promise<ReferenceSyncBlockData>;
49
52
  /**
@@ -54,6 +57,7 @@ declare class BlockServiceADFFetchProvider implements ADFFetchProvider {
54
57
  batchFetchData(blockNodeIdentifiers: BlockNodeIdentifiers[]): Promise<SyncBlockInstance[]>;
55
58
  /**
56
59
  * Subscribes to real-time updates for a specific block using GraphQL WebSocket subscriptions.
60
+ * If a Relay environment is provided, uses Relay subscriptions; otherwise falls back to WebSocket.
57
61
  * @param resourceId - The resource ID of the block to subscribe to
58
62
  * @param onUpdate - Callback function invoked when the block is updated
59
63
  * @param onError - Optional callback function invoked on subscription errors
@@ -91,8 +95,9 @@ interface BlockServiceAPIProvidersProps {
91
95
  parentAri: string | undefined;
92
96
  parentId?: string;
93
97
  product: SyncBlockProduct;
98
+ relayEnvironment?: IEnvironment;
94
99
  }
95
- export declare const useMemoizedBlockServiceAPIProviders: ({ cloudId, parentAri, parentId, product, getVersion, }: BlockServiceAPIProvidersProps) => {
100
+ export declare const useMemoizedBlockServiceAPIProviders: ({ cloudId, parentAri, parentId, product, getVersion, relayEnvironment, }: BlockServiceAPIProvidersProps) => {
96
101
  fetchProvider: BlockServiceADFFetchProvider;
97
102
  writeProvider: BlockServiceADFWriteProvider;
98
103
  };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @generated SignedSource<<559b4fb25d0e5bc72be383427a939e2d>>
3
+ * @relayHash 38684212c43376e58fea2d6095011652
4
+ * @lightSyntaxTransform
5
+ * @nogrep
6
+ * @codegen-command: yarn relay
7
+ */
8
+ import type { ConcreteRequest } from 'relay-runtime';
9
+ export type relaySubscriptionUtilsSubscription$variables = {
10
+ resourceId: string;
11
+ };
12
+ export type relaySubscriptionUtilsSubscription$data = {
13
+ readonly blockService_onBlockUpdated: {
14
+ readonly blockAri: string;
15
+ readonly blockInstanceId: string;
16
+ readonly content: string;
17
+ readonly contentUpdatedAt: number | null | undefined;
18
+ readonly createdAt: number;
19
+ readonly createdBy: string;
20
+ readonly deletionReason: string | null | undefined;
21
+ readonly product: string;
22
+ readonly sourceAri: string;
23
+ readonly status: string;
24
+ } | null | undefined;
25
+ };
26
+ export type relaySubscriptionUtilsSubscription = {
27
+ response: relaySubscriptionUtilsSubscription$data;
28
+ variables: relaySubscriptionUtilsSubscription$variables;
29
+ };
30
+ declare const node: ConcreteRequest;
31
+ export default node;
@@ -0,0 +1,47 @@
1
+ import { type ParsedBlockSubscriptionData } from '../clients/block-service/sharedSubscriptionUtils';
2
+ import type { ResourceId } from '../common/types';
3
+ import type { SyncBlockInstance } from '../providers/types';
4
+ export type RelayBlockUpdateResponse = {
5
+ blockAri: string;
6
+ blockInstanceId: string;
7
+ content: string;
8
+ contentUpdatedAt?: number | null;
9
+ createdAt: number;
10
+ createdBy: string;
11
+ deletionReason?: string | null;
12
+ product: string;
13
+ sourceAri: string;
14
+ status: string;
15
+ };
16
+ /**
17
+ * Converts parsed subscription data to SyncBlockInstance format.
18
+ *
19
+ * @param parsed - The parsed subscription data
20
+ * @param resourceId - The resource ID for the block
21
+ * @returns A SyncBlockInstance
22
+ */
23
+ export declare function convertParsedDataToSyncBlockInstance(parsed: ParsedBlockSubscriptionData, resourceId: ResourceId): SyncBlockInstance;
24
+ /**
25
+ * Converts a Relay subscription response to SyncBlockInstance format using shared parsing logic.
26
+
27
+ * @param response - The Relay subscription response containing block update data
28
+ * @param resourceId - The resource ID for the block
29
+ * @returns A SyncBlockInstance or null if parsing fails
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // In a Relay subscription handler
34
+ * onNext: (response) => {
35
+ * if (response?.blockService_onBlockUpdated) {
36
+ * const syncBlockInstance = convertRelayResponseToSyncBlockInstance(
37
+ * response.blockService_onBlockUpdated,
38
+ * resourceId,
39
+ * );
40
+ * if (syncBlockInstance) {
41
+ * onUpdate(syncBlockInstance);
42
+ * }
43
+ * }
44
+ * }
45
+ * ```
46
+ */
47
+ export declare function convertRelayResponseToSyncBlockInstance(response: RelayBlockUpdateResponse, resourceId: ResourceId): SyncBlockInstance | null;