209 embedpdf viewer#210
Conversation
…an/corates into 209-embedpdf-viewer
…an/corates into 209-embedpdf-viewer
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughWalkthroughThe PR integrates EmbedPDF as an alternate PDF viewer alongside the existing PdfViewer, adding mode-based selection via configuration, wrapper components, PDF virtualization for large-file rendering efficiency, and database migration/script updates for production workflows. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant ChecklistWithPdf
participant Config as PDF_VIEWER_MODE
participant EmbedPdfViewer
participant ViewerSnippet as EmbedPdfViewerSnippet
participant ViewerPdfJs as EmbedPdfViewerPdfJs
participant PdfViewer
User->>ChecklistWithPdf: Render with pdfData
ChecklistWithPdf->>Config: Read PDF_VIEWER_MODE
alt mode === 'snippet'
ChecklistWithPdf->>EmbedPdfViewer: Render (pdfData, pdfFileName, readOnly)
EmbedPdfViewer->>ViewerSnippet: Match 'snippet' → Render
ViewerSnippet->>ViewerSnippet: Create blob URL from pdfData
ViewerSnippet->>ViewerSnippet: Initialize EmbedPDF viewer (theme, disabledCategories)
ViewerSnippet->>ViewerSnippet: Setup lifecycle: createEffect + onCleanup
ViewerSnippet->>User: Display PDF with EmbedPDF UI
else mode === 'pdfjs' (default)
ChecklistWithPdf->>EmbedPdfViewer: Render (pdfData, pdfFileName, readOnly)
EmbedPdfViewer->>ViewerPdfJs: Match 'pdfjs' → Render
ViewerPdfJs->>PdfViewer: Render with pdfData, pdfFileName
PdfViewer->>User: Display PDF with pdfjs backend
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
corates | ffe4b93 | Commit Preview URL | Jan 04 2026, 02:27 AM |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (6)
packages/workers/scripts/reset-db-prod.mjs (1)
149-160: Verification checks only one table; consider broadening the check.The verification only confirms that the
verificationtable exists. This is a narrow check that may miss failures in other critical tables likeuser,projects, ororganization. A single table check provides limited confidence that the migration succeeded completely.Suggested improvements
Check for multiple critical tables to increase confidence:
- // Verify critical tables were created console.log(' Verifying tables were created...'); const verifyResult = runWranglerD1Execute( - "SELECT name FROM sqlite_master WHERE type='table' AND name='verification';", + "SELECT name FROM sqlite_master WHERE type='table' AND name IN ('user', 'projects', 'organization', 'verification') ORDER BY name;", { allowFailure: true }, ); - if (!verifyResult.stdout || !verifyResult.stdout.includes('verification')) { - console.error(' WARNING: verification table was not created!'); + const expectedTables = ['user', 'projects', 'organization', 'verification']; + const missingTables = expectedTables.filter(table => !verifyResult.stdout.includes(table)); + if (missingTables.length > 0) { + console.error(` WARNING: Missing tables: ${missingTables.join(', ')}`); console.error(' Migration may have failed or been skipped.'); - throw new Error('Migration verification failed: verification table missing'); + throw new Error(`Migration verification failed: missing tables: ${missingTables.join(', ')}`); } - console.log(' Verification table exists'); + console.log(' All critical tables verified');packages/web/src/config/pdfViewer.js (1)
1-9: Consider validating PDF_VIEWER_MODE value.The configuration accepts any value from the environment variable without validation. If someone sets
VITE_PDF_VIEWER_MODE=invalid, the application will use that invalid mode, potentially causing runtime errors in components that depend on this value.Suggested validation
+const VALID_MODES = ['pdfjs', 'snippet']; +const mode = import.meta.env.VITE_PDF_VIEWER_MODE || 'pdfjs'; + // PDF viewer implementation mode: // - 'pdfjs': Uses PDF.js with custom UI (default) // - 'snippet': Uses EmbedPDF snippet viewer with full UI (toolbar, sidebar, etc.) -export const PDF_VIEWER_MODE = import.meta.env.VITE_PDF_VIEWER_MODE || 'pdfjs'; +export const PDF_VIEWER_MODE = VALID_MODES.includes(mode) ? mode : 'pdfjs'; + +if (!VALID_MODES.includes(mode) && mode !== 'pdfjs') { + console.warn( + `Invalid PDF_VIEWER_MODE "${mode}". Valid modes: ${VALID_MODES.join(', ')}. Falling back to 'pdfjs'.` + ); +}packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx (1)
13-21: Incomplete JSDoc@returnsannotation.The
@returnstag is empty. Consider completing it or removing the incomplete annotation.Proposed fix
/** * EmbedPdfViewer - Component for viewing PDF files using EmbedPDF snippet viewer * @param {Object} props - Component props * @param {ArrayBuffer} props.pdfData - ArrayBuffer of PDF data (required) * @param {string} props.pdfFileName - Name of the PDF file (optional, for display) * @param {boolean} props.readOnly - If true, view only mode - * - * @returns + * @returns {JSX.Element} The PDF viewer component */packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx (2)
267-313: Consider reusingdestroyViewer()inonCleanupto reduce duplication.The cleanup logic duplicates most of
destroyViewer(). While the extra safety check for the memo'sblobUrl()is valid, the duplication increases maintenance burden.Proposed simplification
// Clean up on unmount onCleanup(() => { - // Destroy viewer instance - if (viewerInstance) { - try { - if (typeof viewerInstance.destroy === 'function') { - viewerInstance.destroy(); - } else if (typeof viewerInstance.unmount === 'function') { - viewerInstance.unmount(); - } else if (typeof viewerInstance.dispose === 'function') { - viewerInstance.dispose(); - } - } catch (err) { - console.warn('Error destroying EmbedPDF viewer on cleanup:', err); - } - viewerInstance = null; - } - - // Clear container contents - if (containerRef) { - try { - containerRef.innerHTML = ''; - } catch (err) { - console.warn('Error clearing container:', err); - } - } - - // Revoke blob URL (only the current one to avoid double-revoking) - if (currentBlobUrl) { - try { - URL.revokeObjectURL(currentBlobUrl); - } catch (err) { - console.warn('Error revoking blob URL:', err); - } - currentBlobUrl = null; - } + destroyViewer(); // Also revoke the current blobUrl if different (shouldn't happen, but safety check) const url = blobUrl(); if (url && url !== currentBlobUrl) { try { URL.revokeObjectURL(url); } catch (err) { console.warn('Error revoking blob URL:', err); } } });
317-327: UseShowcomponent instead of ternary operator for conditional rendering.Per coding guidelines, prefer Solid's
Showcomponent for conditional rendering instead of ternary operators.Proposed fix
+import { createMemo, createEffect, onCleanup, Show } from 'solid-js'; ... - const hasPdfData = createMemo(() => !!props.pdfData); - return ( <div class='h-full w-full bg-gray-100'> - {hasPdfData() ? + <Show + when={props.pdfData} + fallback={ + <div class='flex h-full items-center justify-center'> + <div class='text-center text-gray-500'> + <p>No PDF selected</p> + </div> + </div> + } + > <div ref={containerRef} class='h-full w-full' /> - : <div class='flex h-full items-center justify-center'> - <div class='text-center text-gray-500'> - <p>No PDF selected</p> - </div> - </div> - } + </Show> </div> );packages/web/src/components/checklist/pdf/pdfVirtualization.js (1)
227-231: Consider logging errors in the catch block for debugging.The catch block silently swallows errors and falls back to default heights. While the fallback is correct behavior, logging the error would help identify issues during development.
Proposed fix
- } catch { + } catch (err) { + console.warn('Failed to precompute page heights, using defaults:', err); // Fall back to default height estimate if precompute fails. rebuildPrefixOffsets({ preserveScroll: true }); handleScroll(); }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (18)
.gitignorepackages/web/package.jsonpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/pdf/PdfViewer.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/config/pdfViewer.jspackages/workers/migrations/0000_needy_puff_adder.sqlpackages/workers/migrations/meta/0000_snapshot.jsonpackages/workers/migrations/meta/_journal.jsonpackages/workers/package.jsonpackages/workers/scripts/README.mdpackages/workers/scripts/generate-test-sql.mjspackages/workers/scripts/reset-db-prod.mjs
🧰 Additional context used
📓 Path-based instructions (16)
packages/web/**/!(*.test|*.spec).{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)
packages/web/**/!(*.test|*.spec).{js,ts,jsx,tsx}: Always usehandleFetchErrorfrom@/lib/error-utils.jsfor frontend fetch calls with optionalshowToastparameter
UsecreateFormErrorSignalsfrom@/lib/form-errors.jsfor handling form validation errors, field-level errors, and global errors in frontend forms
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/{web,workers}/**/!(*.test|*.spec).{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)
packages/{web,workers}/**/!(*.test|*.spec).{js,ts,jsx,tsx}: Never throw string literals; always throw Error objects or return domain errors from API routes
UseisErrorCodeutility from@corates/sharedor@/lib/error-utils.jsto check for specific error codes instead of manual error comparisons
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**/*.{js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/form-state.mdc)
packages/web/src/**/*.{js,jsx}: Save form state to IndexedDB before initiating OAuth redirects (Google Drive, ORCID) using saveFormState() with form type ('createProject' or 'addStudies') and serializable state only
Only save serializable data to IndexedDB—exclude File objects, ArrayBuffers, functions, and other non-serializable objects from form state persistence
Restore form state after OAuth redirects by checking URL restore params with getRestoreParamsFromUrl(), retrieving saved state with getFormState(), restoring to form, clearing saved state with clearFormState(), and clearing URL params with clearRestoreParamsFromUrl()
For temporary File object storage during OAuth flows (e.g., pending PDFs), use projectStore.setPendingProjectData() instead of IndexedDB, as File objects cannot be serialized
Add restore parameters to the URL after OAuth redirects in the format '?restore=&projectId=' to signal form state restoration on mount
Clear URL restore parameters after form state restoration by calling clearRestoreParamsFromUrl() to prevent stale restoration attempts on subsequent navigation
Form state persistence library functions (saveFormState, getFormState, clearFormState, getRestoreParamsFromUrl, clearRestoreParamsFromUrl) are implemented in packages/web/src/lib/formStatePersistence.js and should be imported from @/lib/formStatePersistence.js
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/pdf-handling.mdc)
packages/web/src/**/*.{js,jsx,ts,tsx}: Always useuploadPdffrom@api/pdf-api.jsfor uploading PDF files. Pass object with projectId, studyId, tag ('primary' or 'supplementary'), and fileName
Validate PDF files on frontend by checking file.type includes 'pdf' and file.size is within MAX_PDF_SIZE limit (full validation is done on backend)
UsecachePdfandgetCachedPdffrom@primitives/pdfCache.jsfor caching PDF data in IndexedDB
Implement PDF caching strategy: check cache first, download from server if not cached, then cache the downloaded PDF
Store only PDF metadata in Yjs (id, name, size, tag, uploadedAt, uploadedBy), never store PDF binary data in Yjs as it is too large
UseimportFromGoogleDrivefrom@api/google-drive.jsfor importing PDFs from Google Drive. Pass fileId, projectId, studyId, and tag
Save form state usingsaveFormStatefrom@/lib/formStatePersistence.jsbefore triggering OAuth redirects for Google Drive
UseaddPdfToStudyoperation fromuseProjecthook to add PDFs to a study, passing id, name, size, tag, uploadedAt, and uploadedBy
UseremovePdfFromStudyoperation fromuseProjecthook to remove PDFs from a study
UsepdfPreviewStorefrom@/stores/pdfPreviewStore.jsfor managing PDF preview state (openPreview, closePreview, getPreview methods)
UsedownloadPdffrom@api/pdf-api.jsto download PDFs from server, then cache the result usingcachePdf
Always cache PDFs after download and check cache before downloading to avoid redundant downloads
Use PDF operations fromuseProjecthook instead of bypassing through direct API calls
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/solidjs.mdc)
{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}: Use createSignal for simple reactive values in SolidJS components
Use createStore for complex objects and arrays that need granular reactivity in SolidJS
Use createMemo for computed/derived values that depend on reactive state in SolidJS
Always clean up SolidJS effects that create subscriptions or timers using onCleanup
Import stores directly in components and use store read/write action pattern - read from store, write via actions store
Prefer derived state with createMemo or signals over effects whenever possible
Use local createSignal or createStore for local component state; use external stores for shared/cross-feature state
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/{web,ui}/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
packages/{web,ui}/**/*.{js,jsx,ts,tsx}: Import UI components from '@corates/ui' package instead of local components directories
Use solid-icons library for icons instead of emojis or other icon sources
Use Tailwind CSS classes for styling UI components
Apply responsive design using mobile-first approach with Tailwind CSS
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Use import aliases from jsconfig.json (e.g., @/, @components/, @auth-ui/, @checklist-ui/, @project-ui/, @routes/, @primitives/, @api/, @config/, @lib/) instead of relative paths
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/yjs-sync.mdc)
**/*.{js,jsx,ts,tsx}: Use theuseProjecthook for managing Yjs connections with reference counting instead of creating Y.Doc instances directly
Never create Y.Doc instances directly; always use the connection registry managed by useProject
Access Y.Doc connection state via projectStore.getConnectionState(projectId) instead of checking connection state directly
Read Yjs-synced data from projectStore (using getStudies, getChecklist, etc.) rather than accessing Y.Doc maps/arrays directly
Use operation functions from useProject or projectActionsStore for writing data instead of directly modifying Y.Doc
Don't store Y.Doc references in component state; always retrieve the connection through useProject
Handle connection cleanup via onCleanup() in Solid.js components or equivalent cleanup patterns, calling disconnect() when the component unmounts
**/*.{js,jsx,ts,tsx}: For UI icons, usesolid-iconslibrary or SVGs only (never emojis)
Prefer modern ES6+ syntax and features
Use import aliases from jsconfig.json (see ui-components.mdc)
Group related components in subdirectories with barrel exports
Use Ark UI components from@corates/uipackage, NOT local components
Usesolid-iconsicon library (e.g.,solid-icons/bi,solid-icons/fi) for icons
Comments should explain WHY something is being done, not narrate what the code does
Use comments to explain why a particular approach or workaround was chosen
Use comments to clarify intent when code could be misread or misunderstood
Use comments to provide context from external systems, specs, or requirements
Use comments to document assumptions, edge cases, or limitations
Do NOT narrate what the code is doing in comments
Do NOT duplicate function or variable names in plain English in comments
Do NOT leave stale comments that contradict the code
Do NOT reference removed or obsolete code paths in comments
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*: NEVER use emojis anywhere - not in code, comments, documentation, plan files, commit messages, or examples
Do NOT use unicode symbols - unicode symbols are forbidden anywhere in the codebase
Files:
packages/web/src/config/pdfViewer.jspackages/workers/migrations/meta/_journal.jsonpackages/workers/scripts/README.mdpackages/workers/scripts/generate-test-sql.mjspackages/workers/package.jsonpackages/workers/migrations/meta/0000_snapshot.jsonpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/workers/scripts/reset-db-prod.mjspackages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,jsx,js}: For UI icons, usesolid-iconslibrary or SVGs only (never emojis)
Prefer modern ES6+ syntax and features
Use import aliases from jsconfig.json as defined in the ui-components.mdc documentation
Prefer config files over hardcoding values
Ensure browser compatibility (Safari is usually problematic)
Group related components in subdirectories with barrel exports
Use Ark UI components from@corates/uipackage, not local component implementations
Usesolid-iconsicon library (e.g.,solid-icons/bi,solid-icons/fi) for icons
Comments should explain WHY something is being done, not WHAT the code is doing
Comment to explain why a particular approach or workaround was chosen
Comment to clarify intent when code could be misread or misunderstood
Comment to provide context from external systems, specs, or requirements
Comment to document assumptions, edge cases, or limitations
Do NOT comment by narrating what the code is doing
Do NOT duplicate function or variable names in plain English comments
Do NOT leave stale comments that contradict the code
Do NOT reference removed or obsolete code paths in comments
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*.{js,jsx,ts,tsx,css,scss}
📄 CodeRabbit inference engine (.cursor/rules/corates.mdc)
Ensure browser compatibility (Safari is usually problematic)
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**
📄 CodeRabbit inference engine (.cursor/rules/organizations.mdc)
packages/web/src/**: Use human-readable slug in frontend URLs: /orgs/:orgSlug/...
Use orgId (UUID) for API calls, not orgSlug, when making fetch requests to backend endpoints
Files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/pdf-handling.mdc)
Use
PdfViewercomponent from@/components/checklist-ui/pdf/PdfViewer.jsxfor displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange
Files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/PdfViewer.jsx
{packages/web/**,packages/landing/**}/**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/solidjs.mdc)
{packages/web/**,packages/landing/**}/**/*.{jsx,tsx}: NEVER destructure props in SolidJS components - access props directly or wrap in functions to maintain reactivity
Use external stores in packages/web/src/stores/ for shared/cross-feature state instead of prop-drilling
Keep SolidJS components lean and focused on rendering - move business logic to stores, primitives, or utilities
Create reusable logic in primitives (hooks) in packages/web/src/primitives/ and import them into components
Use Solid's Show component for conditional rendering instead of ternary operators
Use Solid's For component for rendering lists instead of Array.map()
Use the children helper when manipulating props.children in SolidJS components
Files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/**/*.{ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/**/*.{ts,tsx,jsx}: Do NOT prop-drill application state in SolidJS - import stores directly where needed
Do NOT destructure props in SolidJS - accessprops.fielddirectly or wrap in function:() => props.field
SolidJS components should receive at most 1-5 props (local config only, not shared state)
Move business logic to stores, utilities, or primitives (not in components) in SolidJS
Files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/corates.mdc)
packages/web/**/*.{jsx,tsx}: Do NOT prop-drill application state in SolidJS - import stores directly where needed
Do NOT destructure props in SolidJS - accessprops.fielddirectly or wrap in function:() => props.field
Shared state lives in external stores underpackages/web/src/stores/
SolidJS components should receive at most 1-5 props (local config only, not shared state)
UsecreateStorefor complex state objects in SolidJS
UsecreateMemofor derived values in SolidJS
Move business logic to stores, utilities, or primitives - not components
Frontend uses orgSlug in URLs (/orgs/:orgSlug/...) for readability
Files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsxpackages/web/src/components/checklist/pdf/PdfViewer.jsx
🧠 Learnings (40)
📓 Common learnings
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use `PdfViewer` component from `@/components/checklist-ui/pdf/PdfViewer.jsx` for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use `PdfViewer` component from `@/components/checklist-ui/pdf/PdfViewer.jsx` for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `pdfPreviewStore` from `@/stores/pdfPreviewStore.js` for managing PDF preview state (openPreview, closePreview, getPreview methods)
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `cachePdf` and `getCachedPdf` from `primitives/pdfCache.js` for caching PDF data in IndexedDB
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use PDF operations from `useProject` hook instead of bypassing through direct API calls
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Store only PDF metadata in Yjs (id, name, size, tag, uploadedAt, uploadedBy), never store PDF binary data in Yjs as it is too large
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Implement PDF caching strategy: check cache first, download from server if not cached, then cache the downloaded PDF
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Validate PDF files on frontend by checking file.type includes 'pdf' and file.size is within MAX_PDF_SIZE limit (full validation is done on backend)
Applied to files:
packages/web/src/config/pdfViewer.jspackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.jspackages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/workers/**/*.{js,ts} : Use Drizzle ORM for ALL database interactions and migrations
Applied to files:
packages/workers/scripts/README.mdpackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T15:42:01.079Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-27T15:42:01.079Z
Learning: Applies to packages/workers/**/*.{ts,tsx} : Use Drizzle ORM for ALL database interactions and migrations
Applied to files:
packages/workers/scripts/README.mdpackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T15:42:01.079Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-27T15:42:01.079Z
Learning: Applies to packages/workers/**/*.{ts,sql} : Use DrizzleKit to generate new migrations when necessary
Applied to files:
packages/workers/scripts/README.mdpackages/workers/scripts/generate-test-sql.mjspackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T03:01:45.070Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-12-27T03:01:45.070Z
Learning: Applies to packages/workers/**/!(*.test|*.spec).{js,ts,jsx,tsx} : Wrap database operations in try-catch blocks and return domain errors using `createDomainError(SYSTEM_ERRORS.DB_ERROR, ...)` with operation metadata
Applied to files:
packages/workers/scripts/README.mdpackages/workers/scripts/generate-test-sql.mjspackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:32:23.479Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/workers.mdc:0-0
Timestamp: 2026-01-01T23:32:23.479Z
Learning: Applies to packages/workers/src/**/*.{js,ts,jsx,tsx} : ALWAYS use `db.batch()` for multiple related database operations in Drizzle to ensure atomicity - all operations must succeed or all fail together
Applied to files:
packages/workers/scripts/README.mdpackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T15:42:01.079Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-27T15:42:01.079Z
Learning: Applies to packages/workers/**/*.sql : Do NOT create separate migration files manually - use DrizzleKit instead
Applied to files:
packages/workers/scripts/README.mdpackages/workers/scripts/generate-test-sql.mjspackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:31:43.748Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.748Z
Learning: Applies to packages/workers/src/routes/**/*.js : Use `db.batch()` for related database operations that must be atomic
Applied to files:
packages/workers/scripts/README.md
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/workers/**/*.sql : Use DrizzleKit to generate new migrations when necessary
Applied to files:
packages/workers/scripts/README.mdpackages/workers/scripts/generate-test-sql.mjspackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/workers/**/*.sql : Do NOT create separate migration files manually (0002_xxx.sql, etc.) - use DrizzleKit instead
Applied to files:
packages/workers/scripts/generate-test-sql.mjspackages/workers/package.jsonpackages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:31:43.748Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.748Z
Learning: Applies to packages/workers/src/routes/**/*.js : Always create DB client from environment using `createDb` function in route handlers
Applied to files:
packages/workers/package.json
📚 Learning: 2026-01-01T23:31:43.748Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.748Z
Learning: Applies to packages/workers/src/routes/**/*.js : Always use Drizzle ORM with query builders - never use raw SQL in database operations
Applied to files:
packages/workers/package.json
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/components/checklist-ui/compare/**,packages/web/src/AMSTAR2/checklist-compare.js} : Use compareChecklists utility from checklist-compare.js for comparing reviewer checklists
Applied to files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `addPdfToStudy` operation from `useProject` hook to add PDFs to a study, passing id, name, size, tag, uploadedAt, and uploadedBy
Applied to files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.json
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Use Solid's Show component for conditional rendering instead of ternary operators
Applied to files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Always use `uploadPdf` from `api/pdf-api.js` for uploading PDF files. Pass object with projectId, studyId, tag ('primary' or 'supplementary'), and fileName
Applied to files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.json
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `removePdfFromStudy` operation from `useProject` hook to remove PDFs from a study
Applied to files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `downloadPdf` from `api/pdf-api.js` to download PDFs from server, then cache the result using `cachePdf`
Applied to files:
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsxpackages/web/package.jsonpackages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/pdf/pdfVirtualization.js
📚 Learning: 2025-12-27T03:01:54.727Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/form-state.mdc:0-0
Timestamp: 2025-12-27T03:01:54.727Z
Learning: Applies to packages/web/src/components/project-ui/**/*.{js,jsx} : Form state should include serializable metadata when handling files (name, size, type) and use the store's pendingPdfs pattern for actual File objects that persist across redirects
Applied to files:
packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx} : Prefer derived state with createMemo or signals over effects whenever possible
Applied to files:
packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Keep SolidJS components lean and focused on rendering - move business logic to stores, primitives, or utilities
Applied to files:
packages/web/src/components/project/PdfPreviewPanel.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx} : Use createMemo for computed/derived values that depend on reactive state in SolidJS
Applied to files:
packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/web/**/*.{jsx,tsx} : Use `createMemo` for derived values in SolidJS
Applied to files:
packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js,packages/web/src/primitives/useProject/checklists.js : Use checklist operations from useProject hook (createChecklist, updateChecklistAnswer, getChecklistData) instead of manually updating checklist structure
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsxpackages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/** : Use NoteEditor component from @/components/checklist-ui/common/NoteEditor.jsx for question note editing with max 2000 character limit
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/primitives/useProject/checklists.js : Store question notes as Y.Text objects obtained from useProject hook via getQuestionNote operation to enable collaborative editing
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to packages/web/src/components/checklist-ui/compare/** : Use Y.Text objects for collaborative editing of question notes in reconciliation
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js : Use getChecklistStatus utility from @/lib/checklist-domain.js to determine current checklist status before performing operations
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/lib/checklist-domain.js : Register and retrieve checklists using checklist-registry: getChecklistType and getChecklistComponent functions
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/** : Use scoreChecklist utility from @/AMSTAR2/checklist.js to determine quality assessment rating: 'High' | 'Moderate' | 'Low' | 'Critically Low'
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js : Maintain separate answer format implementations for each checklist type (AMSTAR2, ROBINS-I, Generic) to prevent data corruption
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/ROBINS-I/** : Use scoreChecklist utility from @/ROBINS-I/checklist.js to determine risk of bias rating: 'Low' | 'Moderate' | 'Serious' | 'Critical'
Applied to files:
packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Use the children helper when manipulating props.children in SolidJS components
Applied to files:
packages/web/src/components/checklist/SplitScreenLayout.jsx
🧬 Code graph analysis (4)
packages/workers/scripts/generate-test-sql.mjs (2)
packages/workers/scripts/reset-db-prod.mjs (1)
__dirname(13-13)packages/workers/scripts/generate-openapi.mjs (1)
__dirname(16-16)
packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx (3)
packages/web/src/config/pdfViewer.js (2)
PDF_VIEWER_MODE(9-9)PDF_VIEWER_MODE(9-9)packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx (1)
EmbedPdfViewerSnippet(14-329)packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx (1)
EmbedPdfViewerPdfJs(8-13)
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx (1)
packages/web/src/components/checklist/pdf/PdfViewer.jsx (1)
PdfViewer(31-120)
packages/web/src/components/project/PdfPreviewPanel.jsx (2)
packages/web/src/stores/pdfPreviewStore.js (1)
pdfPreviewStore(69-84)packages/web/src/components/checklist/pdf/PdfViewer.jsx (1)
PdfViewer(31-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: corates
| .wrangler | ||
| .turbo | ||
| /reference | ||
| reference/ |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check for any reference directories in the repository
echo "=== All reference directories ==="
fd --type d --full-path 'reference$' --exclude node_modules --exclude .git 2>/dev/null || echo "No reference directories found"
echo ""
echo "=== Current .gitignore content (around line 13) ==="
if [ -f .gitignore ]; then
sed -n '10,16p' .gitignore
fiRepository: InfinityBowman/corates
Length of output: 216
🏁 Script executed:
#!/bin/bash
# Check git history for .gitignore changes
echo "=== Recent .gitignore changes ==="
git log --oneline -n 20 -- .gitignore
echo ""
echo "=== Previous .gitignore content (showing reference pattern) ==="
git log -p -- .gitignore | grep -A 5 -B 5 'reference' | head -30
echo ""
echo "=== Commit that modified the reference pattern ==="
git log -p -- .gitignore | grep -B 20 'reference/' | grep -E '^\+reference/|^-/reference|^commit|^Author' | head -20Repository: InfinityBowman/corates
Length of output: 297
Verify whether the reference directory ignore pattern change was intentional.
The pattern reference/ (matches any level) is technically broader than /reference (root-only), as noted. However, no reference/ directories currently exist in the repository that would be newly ignored by this change. If this broadening was unintentional, it should be reverted to /reference; if intentional to catch future reference/ directories at any level, the broader pattern is acceptable.
🤖 Prompt for AI Agents
.gitignore around line 13: the entry "reference/" is broader than the root-only
pattern "/reference" and may unintentionally ignore any nested reference/
directories; confirm whether the broader match was intended — if it was
unintentional, change the line back to "/reference" and commit the revert; if it
was intentional, keep "reference/" but add a brief comment above explaining the
reason (or update repo documentation) so future contributors understand why
nested reference/ dirs should be ignored.
| "analyze": "vite build --mode analyze && source-map-explorer dist/assets/index-*.js --no-border-checks" | ||
| }, | ||
| "dependencies": { | ||
| "@corates/embedpdf-solid": "workspace:*", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify the embedpdf-solid workspace package exists and has proper exports
# Check if the workspace package directory exists
if [ -d "packages/embedpdf-solid" ]; then
echo "=== embedpdf-solid package found ==="
cat packages/embedpdf-solid/package.json | jq '{name, version, exports, main}'
echo ""
echo "=== Checking for component exports ==="
fd --type f '\.(jsx?|tsx?)$' packages/embedpdf-solid/src -x echo {}
else
echo "ERROR: packages/embedpdf-solid directory not found in workspace"
exit 1
fi
echo ""
echo "=== Checking usage in web package ==="
rg --type ts --type tsx -C3 "@corates/embedpdf-solid" packages/web/srcRepository: InfinityBowman/corates
Length of output: 129
🏁 Script executed:
#!/bin/bash
# List all packages in the workspace
echo "=== Packages in workspace ==="
ls -la packages/
echo ""
echo "=== Searching for embedpdf-solid references in codebase ==="
rg "embedpdf-solid" --type json --type ts --type tsx --type js
echo ""
echo "=== Checking package.json workspace configuration ==="
cat pnpm-workspace.yaml 2>/dev/null || cat lerna.json 2>/dev/null || echo "No workspace config found"
echo ""
echo "=== Checking for pdf-related packages ==="
ls -la packages/ | grep -i pdfRepository: InfinityBowman/corates
Length of output: 902
🏁 Script executed:
#!/bin/bash
echo "=== Checking for import attempts in web package ==="
rg "embedpdf-solid|from.*embedpdf" packages/web/src/ --type ts --type tsx --type js
echo ""
echo "=== Full web package.json content ==="
cat packages/web/package.jsonRepository: InfinityBowman/corates
Length of output: 2068
Remove unused workspace dependency or create the missing package.
The dependency @corates/embedpdf-solid was added to packages/web/package.json but the package does not exist in the monorepo (no packages/embedpdf-solid directory found), and there are no imports of this package anywhere in the codebase. The workspace:* reference will cause install failures. Either remove this dependency if it's not needed, or ensure the packages/embedpdf-solid package is created and properly exported as part of this PR.
🤖 Prompt for AI Agents
In packages/web/package.json at line 20, the workspace dependency
"@corates/embedpdf-solid": "workspace:*" references a package that doesn't exist
in the monorepo and causes install failures; remove this dependency from
package.json if the package is not needed, or instead add a new package under
packages/embedpdf-solid with a valid package.json and exports, and update any
imports to reference it; ensure workspace entries and the root
package.json/lerna/yarn workspaces config are updated and that CI installs
successfully.
| "@embedpdf/core": "^2.1.1", | ||
| "@embedpdf/engines": "^2.1.1", | ||
| "@embedpdf/models": "^2.1.1", | ||
| "@embedpdf/plugin-document-manager": "^2.1.1", | ||
| "@embedpdf/plugin-render": "^2.1.1", | ||
| "@embedpdf/plugin-scroll": "^2.1.1", | ||
| "@embedpdf/plugin-viewport": "^2.1.1", | ||
| "@embedpdf/snippet": "^2.0.0", |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
@embedpdf/core npm package version 2.1.1
💡 Result:
I couldn't find an @embedpdf/core v2.1.1 on npm. The official npm package page lists version 1.0.26 as the current published version. [1]
There are other EmbedPDF packages (e.g., @embedpdf/pdfium, some plugins) with versions 2.1.1, but not @embedpdf/core. [2][3]
Sources:
- npm page for @embedpdf/core. [1]
- jsDelivr listing for @embedpdf/pdfium (example of a different package at v2.1.1). [2]
- package metadata summary showing other @embedpdf packages/versions. [3]
Would you like me to watch for a @embedpdf/core v2.1.1 release and notify you?
🌐 Web query:
@embedpdf/engines npm package version 2.1.1
💡 Result:
I couldn't find a published @embedpdf/engines version 2.1.1 on npm. The npm package currently shows version 1.0.20 (most recent publish info on the npm page), and third‑party trackers list recent releases in the 1.x range. [1][2]
If you want, I can:
- check again for a specific publish date or tarball URL, or
- search the package's GitHub releases/tags for a 2.1.1 tag.
🌐 Web query:
@embedpdf/snippet npm package security vulnerabilities
💡 Result:
I found no public security advisories specifically for the npm package @embedpdf/snippet (no entries in Snyk’s database or on EmbedPDF’s GitHub/docs pages). Sources checked: EmbedPDF docs, the project GitHub, jsDelivr/npm metadata and Snyk scans. [1][2][3][4]
If you’re using the package I recommend: run npm audit / yarn audit on your project, scan with Snyk or GitHub Dependabot, and review the package’s dependencies and changelog for recent fixes.
Sources:
- EmbedPDF Snippet docs (package usage). [1]
- EmbedPDF GitHub organization / embed-pdf-viewer repo. [2]
- jsDelivr/npm listing for @embedpdf/snippet. [3]
- Snyk package search (no direct vulnerabilities reported). [4]
🌐 Web query:
embedpdf npm security advisories CVE
💡 Result:
I couldn’t find any public CVE or security advisory specifically for the "embedpdf" or @embedpdf/* packages. npm listings/security scanners show package pages but no CVE entries for those packages. [1]
There are, however, known CVEs affecting other PDF-related npm packages (example: node-qpdf — CVE-2023-26155). If you use any PDF-processing/npm PDF libraries in your project, scan them too. [2][3]
Actions I recommend:
- Run npm audit (or Snyk/Dependabot) against your project to detect known advisories.
- If you want, tell me the exact package name/version you use and I’ll run targeted checks.
Sources:
- @embedpdf plugin/package listings (no CVE shown). [1]
- NVD entry for CVE-2023-26155 (node-qpdf). [2]
- GitLab advisory page for node-qpdf / CVE-2023-26155. [3]
The specified EmbedPDF package versions do not exist on npm and will cause installation failures.
@embedpdf/core v2.1.1 does not exist (current: 1.0.26) and @embedpdf/engines v2.1.1 does not exist (current: 1.x range). Correct these versions before merging. The other @embedpdf packages at ^2.1.1 should also be verified against npm registry. No public security advisories were found for @embedpdf packages.
🤖 Prompt for AI Agents
packages/web/package.json lines 23-30: the pinned @embedpdf/* versions (e.g.
@embedpdf/core @embedpdf/engines and others set to ^2.1.1) do not exist on npm
and will break installs; inspect the npm registry (npm view <pkg> version or npm
info) for each @embedpdf package and replace the non-existent versions with the
correct published versions (for example set @embedpdf/core to 1.0.26 and
@embedpdf/engines to a published 1.x range if that matches the registry), or
change them to a valid semver range (e.g. ^1.x) or to workspace/local paths if
you intended to use unpublished packages; ensure all @embedpdf entries are
updated consistently and run npm install to confirm resolution.
| <EmbedPdfViewer | ||
| pdfData={props.pdfData} | ||
| pdfFileName={props.pdfFileName} | ||
| readOnly={props.readOnly} | ||
| /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find the EmbedPdfViewer component file and examine its function signature
fd -t f 'EmbedPdfViewer.jsx' packages/web/src/Repository: InfinityBowman/corates
Length of output: 131
🏁 Script executed:
#!/bin/bash
# Find the PdfViewer component file and examine its function signature
fd -t f 'PdfViewer.jsx' packages/web/src/Repository: InfinityBowman/corates
Length of output: 187
🏁 Script executed:
#!/bin/bash
# Examine the EmbedPdfViewer component definition
cat -n packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsxRepository: InfinityBowman/corates
Length of output: 1587
🏁 Script executed:
#!/bin/bash
# Examine the PdfViewer component definition - get first 100 lines to see function signature and props
head -100 packages/web/src/components/checklist-ui/pdf/PdfViewer.jsxRepository: InfinityBowman/corates
Length of output: 183
🏁 Script executed:
#!/bin/bash
# Check the ChecklistWithPdf.jsx file around lines 75-79 for context
sed -n '60,90p' packages/web/src/components/checklist/ChecklistWithPdf.jsxRepository: InfinityBowman/corates
Length of output: 783
🏁 Script executed:
#!/bin/bash
# Find and examine PdfViewer component in correct location
head -80 packages/web/src/components/checklist/pdf/PdfViewer.jsxRepository: InfinityBowman/corates
Length of output: 3171
🏁 Script executed:
#!/bin/bash
# Check the EmbedPdfViewerSnippet implementation to see what it supports
head -80 packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsxRepository: InfinityBowman/corates
Length of output: 2678
Document the intentional feature gap between EmbedPdfViewer and PdfViewer modes.
The feature disparity between EmbedPdfViewer and PdfViewer is confirmed. EmbedPdfViewer supports only basic viewing (pdfData, pdfFileName, readOnly), while PdfViewer supports multi-PDF management (onPdfChange, onPdfClear, allowDelete, pdfs, selectedPdfId, onPdfSelect). This appears to be intentional design—the EmbedPdfViewerSnippet implementation relies on the third-party @embedpdf/snippet library which is a simplified viewer. Consider adding:
- A comment in
EmbedPdfViewerexplaining why the snippet viewer has limited features - Documentation distinguishing the capabilities of each mode
- Feature flags or validation to disable snippet mode when features like multi-PDF selection or delete are required
🤖 Prompt for AI Agents
In packages/web/src/components/checklist/ChecklistWithPdf.jsx around lines 75 to
79, the review notes an intentional feature gap between EmbedPdfViewer (basic
snippet viewer: pdfData, pdfFileName, readOnly) and PdfViewer (full-featured:
multi-PDF, onPdfChange/onPdfClear, allowDelete, pdfs, selectedPdfId,
onPdfSelect); add a short comment inside the EmbedPdfViewer component explaining
that it uses the @embedpdf/snippet library and therefore intentionally supports
only basic viewing, update component-level documentation (README or JSDoc) to
clearly list capabilities of EmbedPdfViewer vs PdfViewer, and add runtime
validation or a simple prop-check in ChecklistWithPdf to warn/throw or
automatically select PdfViewer when multi-PDF or delete/select props are passed
(or introduce a feature flag) so callers cannot accidentally rely on unsupported
features.
| export default function EmbedPdfViewerPdfJs(props) { | ||
| // props.pdfData - ArrayBuffer of PDF data (required) | ||
| // props.pdfFileName - Name of the PDF file (optional, for display) | ||
|
|
||
| return <PdfViewer pdfData={props.pdfData} pdfFileName={props.pdfFileName} />; |
There was a problem hiding this comment.
Missing readOnly prop forwarding creates inconsistent behavior.
The EmbedPdfViewer parent passes readOnly to EmbedPdfViewerSnippet but not to this component. However, if this wrapper is meant to be interchangeable with the snippet viewer, it should also respect readOnly to ensure consistent behavior across viewer modes.
Based on learnings, the PdfViewer component accepts readOnly as a prop.
Proposed fix
export default function EmbedPdfViewerPdfJs(props) {
// props.pdfData - ArrayBuffer of PDF data (required)
// props.pdfFileName - Name of the PDF file (optional, for display)
+ // props.readOnly - If true, view only mode (optional)
- return <PdfViewer pdfData={props.pdfData} pdfFileName={props.pdfFileName} />;
+ return <PdfViewer pdfData={props.pdfData} pdfFileName={props.pdfFileName} readOnly={props.readOnly} />;
}Also update EmbedPdfViewer.jsx Line 34 to pass readOnly:
- <EmbedPdfViewerPdfJs pdfData={props.pdfData} pdfFileName={props.pdfFileName} />
+ <EmbedPdfViewerPdfJs pdfData={props.pdfData} pdfFileName={props.pdfFileName} readOnly={props.readOnly} />🤖 Prompt for AI Agents
In packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx around
lines 8-12, the wrapper does not forward the readOnly prop to PdfViewer which
causes inconsistent behavior with other viewers; update the component to pass
props.readOnly into the PdfViewer call (i.e., include readOnly={props.readOnly}
when rendering PdfViewer) and also ensure the parent EmbedPdfViewer.jsx (around
line 34) is updated to pass its readOnly prop down to this wrapper so readOnly
flows from parent to PdfViewer.
| // Create blob URL from pdfData | ||
| const blobUrl = createMemo(() => { | ||
| const pdfData = props.pdfData; | ||
| if (!pdfData) return null; | ||
|
|
||
| const blob = new Blob([pdfData], { type: 'application/pdf' }); | ||
| return URL.createObjectURL(blob); | ||
| }); |
There was a problem hiding this comment.
Potential blob URL memory leak on pdfData changes.
When pdfData changes, createMemo creates a new blob URL, but the previous blob URL from the memo is not revoked. The destroyViewer function only revokes currentBlobUrl (the one actively used by the viewer), not the one held in the memo's reactive closure.
Consider using createEffect with cleanup instead of createMemo for blob URL management, or track the previous URL for explicit revocation.
Proposed approach using createEffect with cleanup
- // Create blob URL from pdfData
- const blobUrl = createMemo(() => {
- const pdfData = props.pdfData;
- if (!pdfData) return null;
-
- const blob = new Blob([pdfData], { type: 'application/pdf' });
- return URL.createObjectURL(blob);
- });
+ // Create blob URL from pdfData with proper cleanup
+ const [blobUrl, setBlobUrl] = createSignal(null);
+
+ createEffect(() => {
+ const pdfData = props.pdfData;
+ if (!pdfData) {
+ setBlobUrl(null);
+ return;
+ }
+
+ const blob = new Blob([pdfData], { type: 'application/pdf' });
+ const url = URL.createObjectURL(blob);
+ setBlobUrl(url);
+
+ onCleanup(() => {
+ URL.revokeObjectURL(url);
+ });
+ });This ensures each blob URL is revoked when the effect re-runs or on unmount.
| viewerInstance.registry.then(registry => { | ||
| try { | ||
| const ui = registry.getPlugin('ui')?.provides(); | ||
| if (ui) { | ||
| const schema = ui.getSchema(); | ||
| const mainToolbar = schema.toolbars?.['main-toolbar']; | ||
|
|
||
| if (mainToolbar?.responsive?.breakpoints) { | ||
| const originalBreakpoints = mainToolbar.responsive.breakpoints; | ||
| // Adjust breakpoints to switch to mobile view at a larger width | ||
| // Preserve all show/hide arrays, only change the width thresholds | ||
| ui.mergeSchema({ | ||
| toolbars: { | ||
| 'main-toolbar': { | ||
| ...mainToolbar, | ||
| responsive: { | ||
| ...mainToolbar.responsive, | ||
| breakpoints: { | ||
| ...originalBreakpoints, | ||
| // Adjust xs breakpoint: keep original, mobile view will start later | ||
| xs: | ||
| originalBreakpoints.xs ? | ||
| { | ||
| ...originalBreakpoints.xs, | ||
| } | ||
| : originalBreakpoints.xs, | ||
| // Adjust sm breakpoint: mobile view now starts at 400px instead of 640px | ||
| // This means desktop mode stays active on smaller screens (until < 400px) | ||
| sm: | ||
| originalBreakpoints.sm ? | ||
| { | ||
| minWidth: 400, // Changed from 640 to 400 (desktop mode stays on smaller screens) | ||
| maxWidth: 768, // Keep maxWidth at 768 | ||
| // Preserve the original show/hide arrays to keep buttons visible | ||
| hide: originalBreakpoints.sm.hide || [], | ||
| show: originalBreakpoints.sm.show || [], | ||
| } | ||
| : originalBreakpoints.sm, | ||
| // Adjust md breakpoint: desktop view now starts at 640px instead of 768px | ||
| // This means desktop mode comes earlier (at smaller screen sizes) | ||
| md: | ||
| originalBreakpoints.md ? | ||
| { | ||
| minWidth: 640, // Changed from 768 to 640 (desktop mode comes earlier) | ||
| // Preserve the original show/hide arrays | ||
| hide: originalBreakpoints.md.hide || [], | ||
| show: originalBreakpoints.md.show || [], | ||
| } | ||
| : originalBreakpoints.md, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
| } | ||
| } | ||
| } catch (err) { | ||
| console.warn('Failed to customize breakpoints:', err); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Potential race condition with async registry.then() callback.
If the effect re-runs (e.g., pdfData changes) while the viewerInstance.registry.then() promise is still pending, the callback may execute on a stale/destroyed viewer instance. The viewerInstance captured in the closure may have been nullified by destroyViewer().
Consider tracking a cancellation token or verifying the instance is still current before modifying the schema.
Proposed fix
+ // Capture current instance for closure
+ const currentInstance = viewerInstance;
+
// Customize responsive breakpoints after initialization
// Adjust mobile view threshold (default is 640px for sm breakpoint)
- viewerInstance.registry.then(registry => {
+ currentInstance.registry.then(registry => {
try {
+ // Verify this is still the active instance
+ if (viewerInstance !== currentInstance) return;
+
const ui = registry.getPlugin('ui')?.provides();
if (ui) {
// ... rest of the code
}
} catch (err) {
console.warn('Failed to customize breakpoints:', err);
}
});🤖 Prompt for AI Agents
In packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
around lines 187 to 246, the registry.then() callback can run after the
component has re-rendered or the viewer has been destroyed, causing schema
modifications on a stale instance; capture a cancellation token or a local
instance id before awaiting registry, then before calling ui.mergeSchema verify
the token/id still matches the current viewer (and that viewerInstance is
non-null and not destroyed); implement a cleanup that increments/invalidates the
token when destroying/recreating the viewer so the callback skips applying the
schema if stale.
| // Also drop migration tracking tables if they exist | ||
| // Wrangler D1 stores migration history in system tables | ||
| console.log(' Dropping migration tracking tables...'); | ||
| runWranglerD1Execute(`DROP TABLE IF EXISTS __drizzle_migrations;`, { allowFailure: true }); | ||
| runWranglerD1Execute(`DROP TABLE IF EXISTS _cf_KV;`, { allowFailure: true }); |
There was a problem hiding this comment.
Dropping __drizzle_migrations breaks migration tracking.
Drizzle ORM uses __drizzle_migrations to track which migrations have been applied. Dropping this table means the system loses all migration history. On the next migration run, Drizzle won't know which migrations were already applied, potentially causing:
- Re-application of migrations (which will fail if tables already exist)
- Inconsistent migration state between environments
- Loss of migration audit trail
Recommended fix
Remove the lines that drop migration tracking tables. These should persist across resets to maintain migration history:
- // Also drop migration tracking tables if they exist
- // Wrangler D1 stores migration history in system tables
- console.log(' Dropping migration tracking tables...');
- runWranglerD1Execute(`DROP TABLE IF EXISTS __drizzle_migrations;`, { allowFailure: true });
- runWranglerD1Execute(`DROP TABLE IF EXISTS _cf_KV;`, { allowFailure: true });If you truly need to reset migration history, the proper workflow is:
- Drop all tables including
__drizzle_migrations - Run migrations with Drizzle, which will recreate
__drizzle_migrationsand record all migrations as applied
However, this is already happening in Step 3 (line 146), so these explicit drops are redundant and harmful.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Also drop migration tracking tables if they exist | |
| // Wrangler D1 stores migration history in system tables | |
| console.log(' Dropping migration tracking tables...'); | |
| runWranglerD1Execute(`DROP TABLE IF EXISTS __drizzle_migrations;`, { allowFailure: true }); | |
| runWranglerD1Execute(`DROP TABLE IF EXISTS _cf_KV;`, { allowFailure: true }); |
🤖 Prompt for AI Agents
In packages/workers/scripts/reset-db-prod.mjs around lines 115 to 119, the
script drops the __drizzle_migrations and _cf_KV tables which removes Drizzle's
migration history and breaks migration tracking; remove the runWranglerD1Execute
calls that drop __drizzle_migrations (and _cf_KV if it’s used for migration
tracking) so migration history is preserved, leaving table drops to the
controlled full-reset workflow (or ensure drops happen only in the explicit
full-reset sequence described in the comments around Step 3).
…an/corates into 209-embedpdf-viewer
…an/corates into 209-embedpdf-viewer
Summary by CodeRabbit
New Features
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.