From 4e15b8fbf5590dfba1617e583d09141f9eca2901 Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:48:04 +0100 Subject: [PATCH] Merge pull request #27868 from overleaf/dp-pdf-preview-2-typescript Convert DocumentCompiler class to typescript GitOrigin-RevId: 6a0d72f7e0cc319c9166ee6236380f6af5187dbb --- .../util/{compiler.js => compiler.ts} | 59 ++++++++++++++++--- .../js/features/pdf-preview/util/types.ts | 5 ++ .../shared/context/local-compile-context.tsx | 7 ++- 3 files changed, 62 insertions(+), 9 deletions(-) rename services/web/frontend/js/features/pdf-preview/util/{compiler.js => compiler.ts} (76%) diff --git a/services/web/frontend/js/features/pdf-preview/util/compiler.js b/services/web/frontend/js/features/pdf-preview/util/compiler.ts similarity index 76% rename from services/web/frontend/js/features/pdf-preview/util/compiler.js rename to services/web/frontend/js/features/pdf-preview/util/compiler.ts index d938cb3893..de265c87a8 100644 --- a/services/web/frontend/js/features/pdf-preview/util/compiler.js +++ b/services/web/frontend/js/features/pdf-preview/util/compiler.ts @@ -1,11 +1,16 @@ import { isMainFile } from './editor-files' import getMeta from '../../../utils/meta' import { deleteJSON, postJSON } from '../../../infrastructure/fetch-json' -import { debounce } from 'lodash' +import { debounce, DebouncedFunc } from 'lodash' import { EDITOR_SESSION_ID, trackPdfDownload } from './metrics' import { enablePdfCaching } from './pdf-caching-flags' import { debugConsole } from '@/utils/debugging' import { signalWithTimeout } from '@/utils/abort-signal' +import { Dispatch, SetStateAction } from 'react' +import { OpenDocuments } from '@/features/ide-react/editor/open-documents' +import { DocumentContainer } from '@/features/ide-react/editor/document-container' +import { CompileResponseData } from '@ol-types/compile' +import { DeliveryLatencies } from './types' const AUTO_COMPILE_MAX_WAIT = 5000 // We add a 2 second debounce to sending user changes to server if they aren't @@ -19,7 +24,33 @@ const PENDING_OP_MAX_WAIT = 10000 const searchParams = new URLSearchParams(window.location.search) +type CompileOptions = { + draft?: boolean + stopOnFirstError?: boolean + isAutoCompileOnLoad?: boolean + isAutoCompileOnChange?: boolean +} + export default class DocumentCompiler { + compilingRef: React.MutableRefObject + projectId: string + setChangedAt: Dispatch> + setCompiling: Dispatch> + setData: Dispatch> + setFirstRenderDone: Dispatch void>> + setDeliveryLatencies: Dispatch> + setError: Dispatch> + cleanupCompileResult: () => void + signal: AbortSignal + openDocs: OpenDocuments + projectRootDocId?: string | null + clsiServerId: string | null + currentDoc: DocumentContainer | null + error: Error | undefined + timer: number + defaultOptions: CompileOptions + debouncedAutoCompile: DebouncedFunc<() => void> + constructor({ compilingRef, projectId, @@ -32,6 +63,18 @@ export default class DocumentCompiler { cleanupCompileResult, signal, openDocs, + }: { + compilingRef: React.MutableRefObject + projectId: string + setChangedAt: Dispatch> + setCompiling: Dispatch> + setData: Dispatch> + setFirstRenderDone: Dispatch void>> + setDeliveryLatencies: Dispatch> + setError: Dispatch> + cleanupCompileResult: () => void + signal: AbortSignal + openDocs: OpenDocuments }) { this.compilingRef = compilingRef this.projectId = projectId @@ -68,7 +111,7 @@ export default class DocumentCompiler { // The main "compile" function. // Call this directly to run a compile now, otherwise call debouncedAutoCompile. - async compile(options = {}) { + async compile(options: CompileOptions = {}) { options = { ...this.defaultOptions, ...options } if (options.isAutoCompileOnLoad && getMeta('ol-preventCompileOnLoad')) { @@ -93,7 +136,6 @@ export default class DocumentCompiler { // reset values this.setChangedAt(0) // TODO: wait for doc:saved? - this.validationIssues = undefined const params = this.buildCompileParams(options) @@ -135,7 +177,7 @@ export default class DocumentCompiler { this.clsiServerId = data.clsiServerId } this.setData(data) - } catch (error) { + } catch (error: any) { debugConsole.error(error) this.cleanupCompileResult() this.setError(error.info?.statusCode === 429 ? 'rate-limited' : 'error') @@ -172,7 +214,7 @@ export default class DocumentCompiler { } // build the query parameters for the compile request - buildCompileParams(options) { + buildCompileParams(options: CompileOptions) { const params = new URLSearchParams() // note: no clsiserverid query param is set on "compile" requests, @@ -190,7 +232,7 @@ export default class DocumentCompiler { // use the feature flag to enable "file line errors" if (searchParams.get('file_line_errors') === 'true') { - params.file_line_errors = 'true' + params.set('file_line_errors', 'true') } return params @@ -227,7 +269,10 @@ export default class DocumentCompiler { }) } - setOption(option, value) { + setOption( + option: Key, + value: CompileOptions[Key] + ) { this.defaultOptions[option] = value } } diff --git a/services/web/frontend/js/features/pdf-preview/util/types.ts b/services/web/frontend/js/features/pdf-preview/util/types.ts index 866b130be4..9c161f0617 100644 --- a/services/web/frontend/js/features/pdf-preview/util/types.ts +++ b/services/web/frontend/js/features/pdf-preview/util/types.ts @@ -48,3 +48,8 @@ export type HighlightData = { width: number height: number } + +export type DeliveryLatencies = { + compileTimeClientE2E?: number + compileTimeServerE2E?: number +} diff --git a/services/web/frontend/js/shared/context/local-compile-context.tsx b/services/web/frontend/js/shared/context/local-compile-context.tsx index 59ce0e90d0..8df64195c0 100644 --- a/services/web/frontend/js/shared/context/local-compile-context.tsx +++ b/services/web/frontend/js/shared/context/local-compile-context.tsx @@ -45,6 +45,7 @@ import { usePdfScrollPosition, } from '@/shared/hooks/use-pdf-scroll-position' import { + DeliveryLatencies, HighlightData, LogEntry, PdfFileDataList, @@ -190,7 +191,9 @@ export const LocalCompileProvider: FC = ({ const [firstRenderDone, setFirstRenderDone] = useState(() => () => {}) // latencies of compile/pdf download/rendering - const [deliveryLatencies, setDeliveryLatencies] = useState({}) + const [deliveryLatencies, setDeliveryLatencies] = useState( + {} + ) // whether the project has been compiled yet const [compiledOnce, setCompiledOnce] = useState(false) @@ -462,7 +465,7 @@ export const LocalCompileProvider: FC = ({ // these are refs rather than state so they don't trigger the effect to run const previousRuleCountsRef = useRef<{ ruleCounts: Record - rootDocId: string + rootDocId: string | null | undefined } | null>(null) const recordedActionsRef = useRef>({}) const recordAction = useCallback((action: string) => {