saves progress on forms when linking google drive account#56
Conversation
WalkthroughAdds IndexedDB-backed form-state persistence and URL restore for OAuth flows; components save state before redirect and restore on return. AddStudies hook gains serialization/restore, provider/context expose persistence hooks, Google Drive launcher awaits pre-save and builds restore callback URLs, and app startup cleans expired states. Changes
Sequence DiagramsequenceDiagram
participant User
participant Form as Project/Create Form
participant AddStudies as AddStudiesForm / Hook
participant Drive as GoogleDrivePickerLauncher
participant IDB as formStatePersistence (IndexedDB)
participant OAuth as OAuth Provider
participant URL as Browser URL
Note over User,Form: User fills project fields and studies
User->>Form: enter fields & add studies
Form->>AddStudies: update internal studies state
Note over User,Drive: Before OAuth redirect
User->>Drive: click "Connect Google Drive"
Drive->>AddStudies: call onSaveFormState()
AddStudies->>Form: request external state (getExternalState)
Form-->>AddStudies: return external state
AddStudies->>IDB: saveFormState(type, mergedState, projectId)
IDB-->>Drive: confirm saved
Drive->>URL: buildRestoreCallbackUrl(type, projectId)
Drive->>OAuth: initiate OAuth redirect (callback includes params)
Note over OAuth,URL: OAuth redirects back with params
OAuth->>URL: redirect to app URL with restore params
Note over URL,Form: On mount after redirect
Form->>URL: getRestoreParamsFromUrl()
URL-->>Form: restore type & projectId
Form->>IDB: getFormState(type, projectId)
IDB-->>Form: return saved state
Form->>AddStudies: pass initialState
AddStudies->>AddStudies: restore internal UI state
Form->>URL: clearRestoreParamsFromUrl()
Form->>IDB: clearFormState(type, projectId)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
corates | 3e4ee03 | Dec 15 2025, 10:41 PM |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
packages/web/src/primitives/useAddStudies.js (1)
949-964: Detached buffer detection could give false negatives.The check
buffer.byteLength === 0 && buffer.maxByteLength === undefinedmay incorrectly identify valid empty buffers as detached. However, thetry-catchblock handles actual detached buffer errors gracefully, so this is a minor edge case.Consider simplifying:
const cloneArrayBuffer = buffer => { if (!buffer || !(buffer instanceof ArrayBuffer)) return null; try { - // Check if buffer is detached by trying to access byteLength - if (buffer.byteLength === 0 && buffer.maxByteLength === undefined) { - return null; - } // Create a new ArrayBuffer copy const copy = new ArrayBuffer(buffer.byteLength); new Uint8Array(copy).set(new Uint8Array(buffer)); return copy; } catch { // Buffer is likely detached return null; } };packages/web/src/components/project-ui/add-studies/AddStudiesContext.jsx (1)
47-61: Consider returning getters for consistency with SolidJS reactivity patterns.The returned object reads context values at call time, so consumers get static values when destructuring. This works for the current OAuth use case where
formTypeandprojectIddon't change, but differs fromuseStudiesContextwhich returns the reactivecontext.studiesobject.If these values need to be reactive in the future, consider returning getters:
return { - formType: context.formType, - projectId: context.projectId, - onSaveFormState: context.onSaveFormState, + get formType() { return context.formType; }, + get projectId() { return context.projectId; }, + get onSaveFormState() { return context.onSaveFormState; }, };For now, the current implementation is acceptable given the static nature of these values per form instance.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
packages/web/src/components/project-ui/AddStudiesForm.jsx(4 hunks)packages/web/src/components/project-ui/CreateProjectForm.jsx(4 hunks)packages/web/src/components/project-ui/ProjectDashboard.jsx(1 hunks)packages/web/src/components/project-ui/add-studies/AddStudiesContext.jsx(2 hunks)packages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsx(2 hunks)packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx(5 hunks)packages/web/src/components/project-ui/tabs/AllStudiesTab.jsx(4 hunks)packages/web/src/lib/formStatePersistence.js(1 hunks)packages/web/src/primitives/useAddStudies.js(2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features.
Use aliases for imports when appropriate to improve readability.
Keep files small, focused, and modular. If a file exceeds a high number of lines, extract sub-modules into a folder with index.jsx, move complex logic into separate utility files or primitives, or split large forms into section components.
Files:
packages/web/src/components/project-ui/ProjectDashboard.jsxpackages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsxpackages/web/src/primitives/useAddStudies.jspackages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/add-studies/AddStudiesContext.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsxpackages/web/src/lib/formStatePersistence.js
**/components/**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/components/**/*.{jsx,tsx}: Keep component files small, focused, and modular, aiming for ~200-300 lines max per component file
When a component exceeds ~300 lines, extract sub-components into a folder (e.g.,ComponentName/withindex.jsxand helper components)
Move complex logic from component files into separate utility files or primitives
In SolidJS components, access props directly from the props object or wrap them in a function instead of destructuring to maintain reactivity
UsecreateMemoto compute derived values based on props or state in SolidJS components
Files:
packages/web/src/components/project-ui/ProjectDashboard.jsxpackages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsxpackages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/add-studies/AddStudiesContext.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsx
**/*.{jsx,tsx,js,ts}
📄 CodeRabbit inference engine (.cursorrules)
Use Solid's
createStorefor complex state or state objects in SolidJS components
Files:
packages/web/src/components/project-ui/ProjectDashboard.jsxpackages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsxpackages/web/src/primitives/useAddStudies.jspackages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/add-studies/AddStudiesContext.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsxpackages/web/src/lib/formStatePersistence.js
packages/web/src/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/src/**/*.{js,jsx,ts,tsx}: For UI icons, use thesolid-iconslibrary or SVGs only. Do not use emojis.
Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file.
When you need to compute a value based on props or state in SolidJS, usecreateMemoto ensure it updates reactively.
For complex state or state objects in SolidJS, use Solid'screateStorefor better performance and reactivity instead of multiplecreateSignalcalls.
Files:
packages/web/src/components/project-ui/ProjectDashboard.jsxpackages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsxpackages/web/src/primitives/useAddStudies.jspackages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/add-studies/AddStudiesContext.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsxpackages/web/src/lib/formStatePersistence.js
packages/web/src/components/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/src/components/**/*.{js,jsx,ts,tsx}: Use responsive design principles for UI components.
Group related components in subdirectories with anindex.jsbarrel export.
Components should receive at most 1–5 props, and only for local configuration, not shared state. If a component would need more than 5 props, move the shared data into an external store, a primitive, or Solid context.
Do NOT destructure props in SolidJS components as it breaks reactivity. Instead, access props directly from the props object (e.g.,props.name) or wrap them in a function (e.g.,const name = () => props.name).
Components should be lean and focused. They should not implement business logic; move that into stores, utilities, or primitives.
When implementing UI components, use zag.js. Reuse existing Zag components inpackages/web/src/components/zag/*as documented in that folder's README.md.
Files:
packages/web/src/components/project-ui/ProjectDashboard.jsxpackages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsxpackages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/add-studies/AddStudiesContext.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsx
packages/web/src/primitives/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Create reusable logic in 'primitives' (hooks) that can be shared across components to keep components clean and focused on rendering.
Files:
packages/web/src/primitives/useAddStudies.js
**/components/**/*[Ff]orm*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Split large forms into section components (see
add-studies/folder pattern)
Files:
packages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsx
🧠 Learnings (6)
📚 Learning: 2025-12-15T16:38:07.301Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-15T16:38:07.301Z
Learning: Applies to **/components/**/*[Ff]orm*.{jsx,tsx} : Split large forms into section components (see `add-studies/` folder pattern)
Applied to files:
packages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsxpackages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/add-studies/AddStudiesContext.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsx
📚 Learning: 2025-12-15T22:11:22.014Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T22:11:22.014Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : For complex state or state objects in SolidJS, use Solid's `createStore` for better performance and reactivity instead of multiple `createSignal` calls.
Applied to files:
packages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsxpackages/web/src/components/project-ui/AddStudiesForm.jsx
📚 Learning: 2025-12-15T16:38:07.301Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-15T16:38:07.301Z
Learning: Applies to **/*.{jsx,tsx,js,ts} : Use Solid's `createStore` for complex state or state objects in SolidJS components
Applied to files:
packages/web/src/components/project-ui/CreateProjectForm.jsxpackages/web/src/components/project-ui/tabs/AllStudiesTab.jsx
📚 Learning: 2025-12-15T16:38:07.301Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-15T16:38:07.301Z
Learning: Create reusable logic in 'primitives' (hooks) that can be shared across SolidJS components
Applied to files:
packages/web/src/components/project-ui/tabs/AllStudiesTab.jsx
📚 Learning: 2025-12-15T16:38:07.301Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-15T16:38:07.301Z
Learning: Reuse existing Zag components: Checkbox, Collapsible, Dialog, FileUpload, PasswordInput, Splitter, Switch, Tabs, Toast, and Tooltip from `packages/web/src/components/zag/`
Applied to files:
packages/web/src/components/project-ui/tabs/AllStudiesTab.jsx
📚 Learning: 2025-12-15T16:38:07.301Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-15T16:38:07.301Z
Learning: Shared or cross-feature state must live in external stores under `packages/web/src/stores/` or relative to the component file
Applied to files:
packages/web/src/lib/formStatePersistence.js
🧬 Code graph analysis (7)
packages/web/src/components/project-ui/ProjectDashboard.jsx (1)
packages/web/src/lib/formStatePersistence.js (1)
getRestoreParamsFromUrl(167-177)
packages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsx (1)
packages/web/src/components/project-ui/add-studies/AddStudiesContext.jsx (2)
useStudiesContext(39-45)useFormPersistenceContext(51-61)
packages/web/src/primitives/useAddStudies.js (2)
packages/web/src/lib/pdfUtils.js (2)
packages/web/src/lib/referenceParser.js (1)
ref(142-147)
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx (2)
packages/web/src/lib/formStatePersistence.js (1)
buildRestoreCallbackUrl(147-161)packages/web/src/api/google-drive.js (3)
connectGoogleAccount(106-132)importFromGoogleDrive(49-73)() => ({})(86-86)
packages/web/src/components/project-ui/tabs/AllStudiesTab.jsx (5)
packages/web/src/components/project-ui/CreateProjectForm.jsx (1)
handleSaveState(62-68)packages/web/src/components/project-ui/ProjectDashboard.jsx (1)
restoreParams(16-16)packages/web/src/lib/formStatePersistence.js (6)
getRestoreParamsFromUrl(167-177)getFormState(79-106)clearFormState(114-128)clearRestoreParamsFromUrl(182-188)state(137-137)saveFormState(49-71)packages/web/src/components/project-ui/AddStudiesForm.jsx (1)
AddStudiesForm(34-351)packages/web/src/primitives/useProjectStudyHandlers.js (1)
handleAddStudies(34-234)
packages/web/src/components/project-ui/add-studies/AddStudiesContext.jsx (2)
packages/web/src/components/project-ui/ProjectContext.jsx (2)
value(33-46)context(52-52)packages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsx (1)
useFormPersistenceContext(15-15)
packages/web/src/lib/formStatePersistence.js (2)
packages/web/src/primitives/pdfCache.js (1)
record(116-124)packages/web/src/components/project-ui/ProjectView.jsx (3)
state(78-112)state(130-164)state(115-127)
⏰ 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
🔇 Additional comments (26)
packages/web/src/lib/formStatePersistence.js (5)
16-30: LGTM!The IndexedDB initialization is correctly implemented with proper error handling and upgrade logic.
136-139: LGTM!Simple and correct wrapper function.
147-161: LGTM!Clean URL construction with proper parameter management.
167-177: LGTM!Correctly parses URL parameters. The type validation happens at the call sites which is acceptable.
182-188: LGTM!Correctly clears URL parameters without triggering navigation.
packages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsx (2)
11-15: LGTM!Context usage follows the documented pattern from
AddStudiesContext.jsx.
67-80: LGTM!Props correctly wired for OAuth state persistence flow.
packages/web/src/components/project-ui/ProjectDashboard.jsx (1)
14-19: LGTM!The OAuth restore detection correctly initializes the form visibility. URL parameter cleanup is appropriately delegated to
CreateProjectForm.packages/web/src/components/project-ui/CreateProjectForm.jsx (4)
1-10: LGTM!Imports are correctly organized for the persistence integration.
36-59: LGTM!The restoration flow correctly handles state recovery and cleanup. Error handling is appropriate for this use case.
62-74: LGTM!State serialization correctly captures both project fields and studies state.
171-180: LGTM!Props correctly configure the persistence flow for the create project form.
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx (3)
17-30: LGTM!Import and JSDoc documentation correctly reflect the new persistence props.
54-74: LGTM!The pre-OAuth state saving and callback URL construction are correctly implemented. State is persisted before the redirect, and errors are properly propagated.
83-86: LGTM!The refactored
connect()call correctly uses internal props for state persistence.packages/web/src/components/project-ui/tabs/AllStudiesTab.jsx (4)
1-18: LGTM!Imports correctly include all required persistence utilities.
29-51: LGTM!The restoration correctly validates both form type and project ID match before restoring state. This prevents cross-project state restoration issues.
54-56: LGTM!State saving correctly includes the project ID for proper scoping.
81-87: LGTM!Props correctly configure the AddStudiesForm for OAuth-aware state persistence.
packages/web/src/primitives/useAddStudies.js (3)
971-1056: LGTM!Comprehensive serialization that correctly handles ArrayBuffers, File objects, and Sets for IndexedDB storage.
1062-1134: LGTM!State restoration correctly reconstructs all form state. The minimal file-like objects are sufficient for display purposes since PDFs are already processed.
1188-1191: LGTM!Public API correctly extended with state persistence helpers.
packages/web/src/components/project-ui/add-studies/AddStudiesContext.jsx (1)
10-34: LGTM!The getter pattern is consistent with the existing
studiesgetter and follows the same pattern used inProjectContext.jsx. The new form persistence properties are well-documented.packages/web/src/components/project-ui/AddStudiesForm.jsx (3)
47-64: State restoration logic is well-implemented for the OAuth flow.Good use of
createEffectinstead ofonMountsinceinitialStatemay arrive asynchronously. ThehasRestoredStateguard correctly prevents duplicate restoration within a single component instance.One minor note: Line 61 hardcodes
'drive'tab, which is appropriate for the Google Drive OAuth flow. If state restoration is extended to other scenarios in the future, consider saving/restoring the active tab as part of the state.
66-76: LGTM!The save handler correctly collects and combines internal studies state with external state before forwarding to the parent callback. Optional chaining properly handles missing callbacks.
253-258: LGTM!The provider is correctly wired with the new form persistence props, enabling child components to access state persistence capabilities through
useFormPersistenceContext.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/web/src/main.jsx (1)
6-9: Consider optimizing cleanup frequency.The non-blocking approach and best-effort error handling are appropriate for app initialization. However, running cleanup on every app load might be unnecessary. Consider throttling to run once per day using a localStorage timestamp to reduce redundant IndexedDB operations.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/web/src/main.jsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features.
Use aliases for imports when appropriate to improve readability.
Keep files small, focused, and modular. If a file exceeds a high number of lines, extract sub-modules into a folder with index.jsx, move complex logic into separate utility files or primitives, or split large forms into section components.
Files:
packages/web/src/main.jsx
**/*.{jsx,tsx,js,ts}
📄 CodeRabbit inference engine (.cursorrules)
Use Solid's
createStorefor complex state or state objects in SolidJS components
Files:
packages/web/src/main.jsx
packages/web/src/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/src/**/*.{js,jsx,ts,tsx}: For UI icons, use thesolid-iconslibrary or SVGs only. Do not use emojis.
Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file.
When you need to compute a value based on props or state in SolidJS, usecreateMemoto ensure it updates reactively.
For complex state or state objects in SolidJS, use Solid'screateStorefor better performance and reactivity instead of multiplecreateSignalcalls.
Files:
packages/web/src/main.jsx
🧠 Learnings (1)
📚 Learning: 2025-12-15T16:38:07.301Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-15T16:38:07.301Z
Learning: Applies to **/*.{jsx,tsx,js,ts} : Use Solid's `createStore` for complex state or state objects in SolidJS components
Applied to files:
packages/web/src/main.jsx
🧬 Code graph analysis (1)
packages/web/src/main.jsx (1)
packages/web/src/lib/formStatePersistence.js (1)
cleanupExpiredStates(195-222)
⏰ 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
🔇 Additional comments (1)
packages/web/src/main.jsx (1)
4-4: LGTM!The import uses the alias convention appropriately and follows ES6+ best practices.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/web/src/lib/formStatePersistence.js (1)
16-30: Consider adding IndexedDB feature detection.The module assumes IndexedDB is available but doesn't check for browser support. While IndexedDB is well-supported in modern browsers, adding a feature check could improve error handling for edge cases.
function openDB() { return new Promise((resolve, reject) => { + if (!window.indexedDB) { + reject(new Error('IndexedDB is not supported in this browser')); + return; + } const request = indexedDB.open(DB_NAME, DB_VERSION);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/web/src/lib/formStatePersistence.js(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features.
Use aliases for imports when appropriate to improve readability.
Keep files small, focused, and modular. If a file exceeds a high number of lines, extract sub-modules into a folder with index.jsx, move complex logic into separate utility files or primitives, or split large forms into section components.
Files:
packages/web/src/lib/formStatePersistence.js
**/*.{jsx,tsx,js,ts}
📄 CodeRabbit inference engine (.cursorrules)
Use Solid's
createStorefor complex state or state objects in SolidJS components
Files:
packages/web/src/lib/formStatePersistence.js
packages/web/src/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/src/**/*.{js,jsx,ts,tsx}: For UI icons, use thesolid-iconslibrary or SVGs only. Do not use emojis.
Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file.
When you need to compute a value based on props or state in SolidJS, usecreateMemoto ensure it updates reactively.
For complex state or state objects in SolidJS, use Solid'screateStorefor better performance and reactivity instead of multiplecreateSignalcalls.
Files:
packages/web/src/lib/formStatePersistence.js
⏰ 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
🔇 Additional comments (5)
packages/web/src/lib/formStatePersistence.js (5)
49-82: DB connection handling looks correct.The transaction-level error handlers (
tx.onerrorandtx.onabort) properly ensure the database is closed in all code paths. The past review concern about DB connection leaks has been addressed.
140-165: DB connection handling is correct.Transaction-level handlers ensure the database is properly closed in all cases. The past review concern has been addressed.
173-225: URL and utility functions look good.The utility functions correctly handle form state checking and URL parameter manipulation. The use of
history.replaceStateto clear params without navigation is appropriate.
232-272: Cleanup function handles errors correctly.The transaction-level error handlers ensure the database is closed even if cursor operations fail. The past review concerns about DB leaks and unhandled
cursor.delete()failures have been addressed—transaction-level handlers will catch any failures during cursor iteration.
42-48: Verify data sensitivity and consider encryption.IndexedDB stores data unencrypted in the browser's local storage. Depending on what form data is being persisted (e.g., PII, credentials, sensitive project details), this could pose a security risk.
Please verify:
- What types of data are being saved through this module (review call sites in CreateProjectForm.jsx, AllStudiesTab.jsx, etc.)
- Whether any of that data is sensitive or includes PII
- If sensitive data is stored, consider adding encryption before saving to IndexedDB
If sensitive data is confirmed, you may want to explore using the Web Crypto API for encryption/decryption.
| if (!record || Date.now() - record.timestamp > MAX_AGE_MS) { | ||
| if (record) { | ||
| clearFormState(type, projectId).catch(() => {}); | ||
| } | ||
| result = null; | ||
| } else { | ||
| result = record.data; | ||
| } |
There was a problem hiding this comment.
Silent error swallowing may hide cleanup failures.
Line 109 uses .catch(() => {}) to silently ignore errors from clearFormState. While this prevents cleanup failures from blocking the read operation, it could hide persistent storage issues.
Consider logging the error for debugging:
if (!record || Date.now() - record.timestamp > MAX_AGE_MS) {
if (record) {
- clearFormState(type, projectId).catch(() => {});
+ clearFormState(type, projectId).catch(err => {
+ console.warn('Failed to cleanup expired form state:', err);
+ });
}
result = null;🤖 Prompt for AI Agents
In packages/web/src/lib/formStatePersistence.js around lines 107-114 the code
currently swallows errors from clearFormState using .catch(() => {}) which hides
persistent storage failures; change the catch to log the error (include type and
projectId and any relevant metadata like record.timestamp) using the project’s
logger or console.error, and retain the non-throwing behavior so the read still
returns null after attempting cleanup.
saves progress on forms when linking google drive account
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.