UNPKG

@backstage/plugin-techdocs

Version:

The Backstage plugin that renders technical documentation for your components

174 lines (171 loc) 4.99 kB
import { useApi } from '@backstage/core-plugin-api'; import { useReducer, useRef, useMemo } from 'react'; import useAsync from 'react-use/esm/useAsync'; import useAsyncRetry from 'react-use/esm/useAsyncRetry'; import { techdocsStorageApiRef } from '@backstage/plugin-techdocs-react'; function calculateDisplayState({ contentLoading, content, activeSyncState }) { if (contentLoading) { return "CHECKING"; } if (activeSyncState === "BUILD_READY_RELOAD") { return "CHECKING"; } if (!content && activeSyncState === "CHECKING") { return "CHECKING"; } if (!content && activeSyncState === "BUILDING") { return "INITIAL_BUILD"; } if (!content) { return "CONTENT_NOT_FOUND"; } if (activeSyncState === "BUILDING") { return "CONTENT_STALE_REFRESHING"; } if (activeSyncState === "BUILD_READY") { return "CONTENT_STALE_READY"; } if (activeSyncState === "ERROR") { return "CONTENT_STALE_ERROR"; } return "CONTENT_FRESH"; } function reducer(oldState, action) { const newState = { ...oldState }; switch (action.type) { case "sync": if (action.state === "CHECKING") { newState.buildLog = []; } newState.activeSyncState = action.state; newState.syncError = action.syncError; break; case "contentLoading": newState.contentLoading = true; newState.contentError = void 0; break; case "content": if (typeof action.path === "string") { newState.path = action.path; } newState.contentLoading = false; newState.content = action.content; newState.contentError = action.contentError; break; case "buildLog": newState.buildLog = newState.buildLog.concat(action.log); break; default: throw new Error(); } if (["BUILD_READY", "BUILD_READY_RELOAD"].includes(newState.activeSyncState) && ["contentLoading", "content"].includes(action.type)) { newState.activeSyncState = "UP_TO_DATE"; newState.buildLog = []; } return newState; } function useReaderState(kind, namespace, name, path) { const [state, dispatch] = useReducer(reducer, { activeSyncState: "CHECKING", path, contentLoading: true, buildLog: [] }); const techdocsStorageApi = useApi(techdocsStorageApiRef); const { retry: contentReload } = useAsyncRetry(async () => { dispatch({ type: "contentLoading" }); try { const entityDocs = await techdocsStorageApi.getEntityDocs( { kind, namespace, name }, path ); dispatch({ type: "content", content: entityDocs, path }); return entityDocs; } catch (e) { dispatch({ type: "content", contentError: e, path }); } return void 0; }, [techdocsStorageApi, kind, namespace, name, path]); const contentRef = useRef({ content: void 0, reload: () => { } }); contentRef.current = { content: state.content, reload: contentReload }; useAsync(async () => { dispatch({ type: "sync", state: "CHECKING" }); const buildingTimeout = setTimeout(() => { dispatch({ type: "sync", state: "BUILDING" }); }, 1e3); try { const result = await techdocsStorageApi.syncEntityDocs( { kind, namespace, name }, (log) => { dispatch({ type: "buildLog", log }); } ); switch (result) { case "updated": if (!contentRef.current.content) { contentRef.current.reload(); dispatch({ type: "sync", state: "BUILD_READY_RELOAD" }); } else { dispatch({ type: "sync", state: "BUILD_READY" }); } break; case "cached": dispatch({ type: "sync", state: "UP_TO_DATE" }); break; default: dispatch({ type: "sync", state: "ERROR", syncError: new Error("Unexpected return state") }); break; } } catch (e) { dispatch({ type: "sync", state: "ERROR", syncError: e }); } finally { clearTimeout(buildingTimeout); } }, [kind, name, namespace, techdocsStorageApi, dispatch, contentRef]); const displayState = useMemo( () => calculateDisplayState({ activeSyncState: state.activeSyncState, contentLoading: state.contentLoading, content: state.content }), [state.activeSyncState, state.content, state.contentLoading] ); return useMemo( () => ({ state: displayState, contentReload, path: state.path, content: state.content, contentErrorMessage: state.contentError?.toString(), syncErrorMessage: state.syncError?.toString(), buildLog: state.buildLog }), [ displayState, contentReload, state.path, state.content, state.contentError, state.syncError, state.buildLog ] ); } export { calculateDisplayState, reducer, useReaderState }; //# sourceMappingURL=useReaderState.esm.js.map