@atlaskit/node-data-provider
Version:
Node data provider for @atlaskit/editor-core plugins and @atlaskit/renderer
215 lines (214 loc) • 8.55 kB
TypeScript
import type { JSONNode } from '@atlaskit/editor-json-transformer';
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
/**
* Represents the SSR data for a single provider.
* It's a map where each key is a unique node data key and the value is the prefetched data for that node.
*
* @example
* {
* 'node-id-1': { value: 'some data' },
* 'node-id-2': { value: 'other data' }
* }
*/
type SSRData<Data> = {
[dataKey: string]: Data;
};
type CacheRecords<Data> = SSRData<Data>;
/**
* Represents the cached data for a Node Data Provider.
* Each key is a unique node data key, and the value is an object containing:
* - `source`: Indicates whether the data was fetched from SSR or the network.
* - `data`: The actual data, which can be either a resolved value or a Promise.
*
* @example
* {
* 'node-id-1': { source: 'ssr', data: { value: 'some data' } },
* 'node-id-2': { source: 'network', data: { value: 'other data' } }
* }
*/
type CacheData<Data> = Record<string, {
data: Data;
source: 'ssr' | 'network';
}>;
/**
* Represents the payload passed to the callback function when data is fetched.
* It can either contain an error or the fetched data.
*/
export type CallbackPayload<Data> = {
data?: undefined;
/** An error that occurred while fetching data. */
error: Error;
} | {
/** Fetched data for the node. */
data: Data;
error?: undefined;
};
/**
* A Node Data Provider is responsible for fetching and caching data associated with specific ProseMirror nodes.
* It supports a cache-first-then-network strategy, with initial data potentially provided via SSR.
*
* @template Node The specific type of JSONNode this provider supports.
* @template Data The type of data this provider fetches and manages.
*/
export declare abstract class NodeDataProvider<Node extends JSONNode, Data> {
private cacheVersion;
private cache;
private readonly networkRequestsInFlight;
/**
* A unique name for the provider. Used for identification in SSR.
*/
abstract readonly name: string;
/**
* A type guard to check if a given JSONNode is supported by this provider.
* Used to ensure that the provider can handle the node type before attempting to fetch data.
*
* @param node The node to check.
* @returns `true` if the node is of the type supported by this provider, otherwise `false`.
*/
abstract isNodeSupported(node: JSONNode): node is Node;
/**
* Generates a unique key for a given node to be used for caching.
*
* @param node The node for which to generate a data key.
* @returns A unique string key for the node's data.
*/
abstract nodeDataKey(node: Node): string;
/**
* Fetches data for a batch of nodes from the network or another asynchronous source.
*
* @param nodes An array of nodes for which to fetch data.
* @returns A promise that resolves to an array of data corresponding to the input nodes.
*/
abstract fetchNodesData(nodes: Node[]): Promise<Data[]>;
protected constructor();
/**
* Sets the SSR data for the provider.
* This pre-populates the cache with data rendered on the server, preventing redundant network requests on the client.
* Calling this method will invalidate the existing cache.
*
* @example
* ```
* const ssrData = window.__SSR_NODE_DATA__ || {};
* nodeDataProvider.setSSRData(ssrData);
* ```
*
* @param ssrData A map of node data keys to their corresponding data.
*/
setSSRData(ssrData?: SSRData<Data>): void;
/**
* Clears all cached data.
* This increments the internal cache version, invalidating any pending network requests.
*
* @example
* ```
* function useMyNodeDataProvider(contentId: string) {
* const nodeDataProvider = new MyNodeDataProvider();
*
* // Reset the cache when the contentId changes (e.g., when the user navigates to a different page).
* useEffect(() => {
* nodeDataProvider.resetCache();
* }, [contentId]);
*
* return nodeDataProvider;
* }
* ```
*/
resetCache(): void;
/**
* Fetches data for a given node using a cache-first-then-network strategy.
*
* The provided callback may be called multiple times:
* 1. Immediately with data from the SSR cache, if available.
* 2. Asynchronously with data fetched from the network.
*
* @example
* ```
* const nodeDataProvider = new MyNodeDataProvider();
*
* nodeDataProvider.getData(node, (data) => {
* console.log('Node data:', data);
* });
* ```
*
* @param node The node (or its ProseMirror representation) for which to fetch data.
* @param callback The callback function to call with the fetched data or an error.
*/
getData(node: Node | PMNode, callback: (payload: CallbackPayload<Data>) => void): void;
protected getDataAsync(node: Node | PMNode, callback: (payload: CallbackPayload<Data>) => void): Promise<void>;
/**
* Fetches data for a given node and returns it as a Promise.
* This is a convenience wrapper around the `data` method for use with async/await.
*
* Note: This promise resolves with the *first* available data, which could be from the SSR cache or the network.
* It may not provide the most up-to-date data if a network fetch is in progress.
*
* Note: This method is only for migration purposes. Use {@link getData} in new code instead.
*
* @private
* @deprecated Don't use this method, use {@link getData} method instead.
* This method is only for migration purposes.
*
* @param node The node (or its ProseMirror representation) for which to fetch data.
* @returns A promise that resolves with the node's data.
*/
getDataAsPromise_DO_NOT_USE_OUTSIDE_MIGRATIONS(node: Node | PMNode): Promise<Data>;
/**
* Checks the cache for the given node and returns its status.
*
* Possible return values:
* - `false`: No cached data found for the node.
* - `'ssr'`: Data is cached from server-side rendering (SSR).
* - `'network'`: Data is cached from a network request.
*
* @param node The node (or its ProseMirror representation) to check in the cache.
* @returns The cache status: `false`, `'ssr'`, or `'network'`.
*/
getCacheStatusForNode(node: Node | PMNode): false | 'ssr' | 'network';
/**
* Retrieves the cached data for a given node, if available.
*
* @param node The node (or its ProseMirror representation) for which to retrieve cached data.
* @returns The cached data object containing `data` and `source`, or `undefined` if no cache entry exists.
*/
getNodeDataFromCache(node: JSONNode | PMNode): CacheData<Data>[string] | undefined;
/**
* Returns the keys of the cache.
*
* @returns An array of the keys of the cache.
*/
getNodeDataCacheKeys(): string[];
/**
* Updates the cache with new records using merge or replace strategies.
* This method should be the only way to modify the cache directly.
* This allow subclasses to use it when needed. e.g. abstract fetchNodesData implementation.
*
* @example
* ```
* const newRecords = {
* 'node-id-1': { value: 'updated data' },
* 'node-id-3': { value: 'new data' }
* };
* nodeDataProvider.updateCache(newRecords, { strategy: 'merge', source: 'network' });
* ```
*
* Supports two strategies:
* - 'merge' (default): Merges new records into the existing cache.
* - 'replace': Replaces the entire cache with the new records, invalidating any in-flight requests.
*
* @param records A map of node data keys to their corresponding data.
* @param options Optional settings for the update operation.
* @param options.strategy The strategy to use for updating the cache ('merge' or 'replace'). Defaults to 'merge'.
* @param options.source The source of the data being added ('ssr' or 'network'). Defaults to 'network'.
*/
updateCache(records?: CacheRecords<Data>, options?: {
source?: 'ssr' | 'network';
strategy?: 'merge' | 'replace';
}): void;
/**
* Removes one or more entries from the cache.
*
* @param keys A single data key or array of data keys to remove from the cache.
*/
removeFromCache(keys: string[]): void;
}
export {};