fix(accounts): deeply compact stored account comments#46
Conversation
📝 WalkthroughWalkthroughIntroduces dual sanitization for comments (live vs persisted), snapshots client runtime state for in-memory entries, and migrates stored account comments by bumping storage version to compact and remove runtime payloads. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Client/UI
participant Actions as accounts-actions
participant DB as Accounts DB
participant State as In-Memory Store
participant IPFS as IPFS Client
UI->>Actions: publishComment(payload)
Actions->>Actions: sanitizeStoredAccountComment -> persistedComment
Actions->>DB: write persistedComment (storage)
Actions->>Actions: sanitizeAccountCommentForState -> liveComment
Actions->>State: insert/update liveComment (in-memory)
Note over State,IPFS: IPFS client later emits statechange
IPFS->>Actions: clientsOnStateChange(state)
Actions->>Actions: getClientsSnapshotForState(...) -> clientsSnapshot
Actions->>State: syncCommentClientsSnapshot(publishSessionId, accountId, clientsSnapshot)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Comment Tip CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.OpenGrep is compatible with Semgrep configurations. Add an |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/stores/accounts/accounts-actions.test.ts (1)
2121-2146:⚠️ Potential issue | 🟡 MinorKeep asserting the live
clientssnapshot here.This test now only checks that the comment still exists. That misses the new behavior added in
accounts-actions.ts: the store should keep a state-onlyclientssnapshot and update it on"statechange". A regression in that path would still pass as long as the pending comment stays in the array, so please keep an assertion onclients.ipfsGateways["https://ipfs.io"].state.Suggested assertion
await new Promise((r) => setTimeout(r, 100)); const comments = accountsStore.getState().accountsComments[account.id] || []; - expect(comments.find((c: any) => c.content === "ipfs")).toBeDefined(); + const ipfsComment = comments.find((c: any) => c.content === "ipfs"); + expect(ipfsComment).toBeDefined(); + expect(ipfsComment?.clients).toEqual( + expect.objectContaining({ + ipfsGateways: { + "https://ipfs.io": { state: "connected" }, + }, + }), + ); });As per coding guidelines
When changing hooks or stores, consider whether existing tests cover the change; if not, add a test.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/stores/accounts/accounts-actions.test.ts` around lines 2121 - 2146, The test currently only asserts the comment exists but must also assert the store's state-only clients snapshot updates on "statechange"; after locating the newly published comment in accountsStore.getState().accountsComments[account.id] (e.g., find by content "ipfs"), assert that comment.clients.ipfsGateways["https://ipfs.io"].state === "connected" (or the expected state string) to cover the behavior added in accounts-actions.publishComment that listens for client "statechange" and updates the snapshot.src/stores/accounts/accounts-database.ts (1)
378-389:⚠️ Potential issue | 🟠 MajorCompact or drop sparse legacy comment slots before stamping v2.
getDatabaseAsArray()returnsundefinedfor missing numeric keys, and this migration currently preserves those gaps while still writing__storageVersion = 2.getAccountComments()later assumes every slot is an object and dereferencescomments[i].index, so a sparse or partially-written legacyaccountCommentsDB will still fail as soon as the account is hydrated or exported. Please densify the array here, or skip falsy rows and rewritelengthduring the migration.Suggested hardening
- const comments = await getDatabaseAsArray(accountCommentsDatabase); - const updatedComments = comments.map((comment) => - comment ? sanitizeStoredAccountComment(comment) : comment, - ); + const comments = await getDatabaseAsArray(accountCommentsDatabase); + const updatedComments = comments + .map((comment) => (comment ? sanitizeStoredAccountComment(comment) : undefined)) + .filter((comment) => comment !== undefined); const rewritePromises: Promise<void>[] = []; for (const [index, updatedComment] of updatedComments.entries()) { if (!isEqual(updatedComment, comments[index])) { rewritePromises.push(accountCommentsDatabase.setItem(String(index), updatedComment)); } } + for (let index = updatedComments.length; index < comments.length; index++) { + rewritePromises.push(accountCommentsDatabase.removeItem(String(index))); + } + rewritePromises.push(accountCommentsDatabase.setItem("length", updatedComments.length)); await Promise.all(rewritePromises); await accountCommentsDatabase.setItem(storageVersionKey, commentStorageVersion);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/stores/accounts/accounts-database.ts` around lines 378 - 389, The migration preserves sparse numeric keys (undefined slots) causing downstream code (getAccountComments) to crash; instead build a dense array by filtering out falsy entries from updatedComments, then rewrite accountCommentsDatabase with contiguous numeric keys 0..N-1 (optionally setting each comment.index = i before writing) — e.g., compute const dense = updatedComments.filter(Boolean), clear or remove old numeric keys, write dense items back with accountCommentsDatabase.setItem(String(i), dense[i]) for each i, and finally set storageVersionKey to commentStorageVersion. Ensure you reference getDatabaseAsArray, sanitizeStoredAccountComment, accountCommentsDatabase, storageVersionKey, and commentStorageVersion when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/stores/accounts/accounts-actions.ts`:
- Around line 1039-1047: Extract the client-snapshot update logic (currently
using getPublishSession(publishSessionId),
getClientsSnapshotForState(comment?.clients) and accountsStore.setState(...)
with maybeUpdateAccountComment) into a helper like
syncCommentClientsSnapshot(publishSessionId, account, comment) that computes the
snapshot and updates accountsComments (including setting undefined to clear the
previous snapshot). Replace the inline block in the original path with a call to
this helper, and invoke the same helper immediately after any retry that
reassigns `comment` (the branch that handles failed challenge verification) so
the live `clients` snapshot is refreshed or cleared on every
createComment()/retry.
---
Outside diff comments:
In `@src/stores/accounts/accounts-actions.test.ts`:
- Around line 2121-2146: The test currently only asserts the comment exists but
must also assert the store's state-only clients snapshot updates on
"statechange"; after locating the newly published comment in
accountsStore.getState().accountsComments[account.id] (e.g., find by content
"ipfs"), assert that comment.clients.ipfsGateways["https://ipfs.io"].state ===
"connected" (or the expected state string) to cover the behavior added in
accounts-actions.publishComment that listens for client "statechange" and
updates the snapshot.
In `@src/stores/accounts/accounts-database.ts`:
- Around line 378-389: The migration preserves sparse numeric keys (undefined
slots) causing downstream code (getAccountComments) to crash; instead build a
dense array by filtering out falsy entries from updatedComments, then rewrite
accountCommentsDatabase with contiguous numeric keys 0..N-1 (optionally setting
each comment.index = i before writing) — e.g., compute const dense =
updatedComments.filter(Boolean), clear or remove old numeric keys, write dense
items back with accountCommentsDatabase.setItem(String(i), dense[i]) for each i,
and finally set storageVersionKey to commentStorageVersion. Ensure you reference
getDatabaseAsArray, sanitizeStoredAccountComment, accountCommentsDatabase,
storageVersionKey, and commentStorageVersion when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f1205d6c-a729-4060-9ddf-9604b1a59791
📒 Files selected for processing (6)
src/stores/accounts/accounts-actions.test.tssrc/stores/accounts/accounts-actions.tssrc/stores/accounts/accounts-database.test.tssrc/stores/accounts/accounts-database.tssrc/stores/accounts/utils.test.tssrc/stores/accounts/utils.ts
|
Addressed the valid review findings in the latest commit. Fixed the sparse legacy accountComments migration by densifying and rewriting the numeric slots before stamping v2, and moved the live clients snapshot sync into a helper that also refreshes or clears the snapshot after retry-created publications. I did not keep the suggested final-state test assertion on comment.clients because successful publishes intentionally clear transport clients from settled account comments; that suggestion would assert the wrong behavior. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/stores/accounts/accounts-actions.ts (2)
62-78: Add brief documentation explaining the expectedclientsstructure.The recursive heuristic at line 66 treats any object with
'state' in clientsas a leaf node. This works for the current structure but could behave unexpectedly if a nested container ever gains astateproperty.Consider adding a brief JSDoc explaining the expected hierarchy (e.g.,
clients.ipfsGateways["url"].state) so future maintainers understand the termination condition.📝 Suggested documentation
+/** + * Extracts a minimal snapshot of the `clients` hierarchy, preserving only + * `{ state }` for each transport client (leaf nodes detected by `.on` method + * or presence of a `state` property). Returns `undefined` when empty. + */ const getClientsSnapshotForState = (clients: any): any => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/stores/accounts/accounts-actions.ts` around lines 62 - 78, Add a short JSDoc above the getClientsSnapshotForState function that documents the expected shape of the clients input (a nested object tree whose leaves are client objects containing a state property, e.g., clients.ipfsGateways["url"].state) and explain the termination heuristic (treat any object with a "state" property or an event-emitter-like "on" method as a leaf). This clarifies why the function checks typeof clients.on === "function" || "state" in clients and warns maintainers that adding a plain "state" property to a non-leaf container will change behavior.
1104-1127: Consider extracting common property deletions to reduce duplication.Both
persistedCommentWithCidandliveCommentWithCidhave the same four properties deleted (lines 1110-1117). While the dual sanitization is intentional (persisted stripsclientsvia sanitizer, live preserves it but then explicitly removes it since CID receipt means publishing is complete), the repeated deletions could be DRYer.♻️ Optional consolidation
const persistedCommentWithCid = addShortAddressesToAccountComment( sanitizeStoredAccountComment(normalizePublicationOptionsForStore(comment as any)), - ); + ) as any; const liveCommentWithCid = addShortAddressesToAccountComment( sanitizeAccountCommentForState(normalizePublicationOptionsForStore(comment as any)), - ); - delete (persistedCommentWithCid as any).clients; - delete (persistedCommentWithCid as any).publishingState; - delete (persistedCommentWithCid as any).error; - delete (persistedCommentWithCid as any).errors; - delete (liveCommentWithCid as any).clients; - delete (liveCommentWithCid as any).publishingState; - delete (liveCommentWithCid as any).error; - delete (liveCommentWithCid as any).errors; + ) as any; + for (const obj of [persistedCommentWithCid, liveCommentWithCid]) { + delete obj.clients; + delete obj.publishingState; + delete obj.error; + delete obj.errors; + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/stores/accounts/accounts-actions.ts` around lines 1104 - 1127, Extract the repeated deletions into a small helper (e.g., stripTransientCommentFields) and call it for both persistedCommentWithCid and liveCommentWithCid instead of repeating delete lines; locate where persistedCommentWithCid and liveCommentWithCid are created (after addShortAddressesToAccountComment/sanitizeStoredAccountComment and sanitizeAccountCommentForState) and replace the eight delete statements with two calls to that helper, ensuring it removes clients, publishingState, error, and errors before calling accountsDatabase.addAccountComment and before building updatedAccountComment for accountsStore.setState.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/stores/accounts/accounts-actions.ts`:
- Around line 62-102: Add assertions in the three publishComment tests that
exercise clients to validate getClientsSnapshotForState behavior: after calling
publishComment, read accountsStore.getState().accountsComments and locate the
stored comment for the publish session index (use
getPublishSession(publishSessionId).currentIndex or the same index used in the
test) and assert (1) when publication.clients contains client objects with
state/on, the accountsComments entry for that index contains a clients snapshot
equal to the expected shape produced by getClientsSnapshotForState; (2) when
publication.clients yields no snapshot (getClientsSnapshotForState returns
undefined), the stored comment has no clients key (clients was deleted by
syncCommentClientsSnapshot); and (3) for nested client structures, assert the
nested keys map to snapshots (state objects) matching the transformation.
Reference getClientsSnapshotForState, syncCommentClientsSnapshot and
maybeUpdateAccountComment to locate where to assert stored results in
accountsStore.
---
Nitpick comments:
In `@src/stores/accounts/accounts-actions.ts`:
- Around line 62-78: Add a short JSDoc above the getClientsSnapshotForState
function that documents the expected shape of the clients input (a nested object
tree whose leaves are client objects containing a state property, e.g.,
clients.ipfsGateways["url"].state) and explain the termination heuristic (treat
any object with a "state" property or an event-emitter-like "on" method as a
leaf). This clarifies why the function checks typeof clients.on === "function"
|| "state" in clients and warns maintainers that adding a plain "state" property
to a non-leaf container will change behavior.
- Around line 1104-1127: Extract the repeated deletions into a small helper
(e.g., stripTransientCommentFields) and call it for both persistedCommentWithCid
and liveCommentWithCid instead of repeating delete lines; locate where
persistedCommentWithCid and liveCommentWithCid are created (after
addShortAddressesToAccountComment/sanitizeStoredAccountComment and
sanitizeAccountCommentForState) and replace the eight delete statements with two
calls to that helper, ensuring it removes clients, publishingState, error, and
errors before calling accountsDatabase.addAccountComment and before building
updatedAccountComment for accountsStore.setState.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9486f3e5-cb72-4a68-b40b-08879b1bd4e8
📒 Files selected for processing (3)
src/stores/accounts/accounts-actions.tssrc/stores/accounts/accounts-database.test.tssrc/stores/accounts/accounts-database.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/stores/accounts/accounts-database.ts
- src/stores/accounts/accounts-database.test.ts
| const getClientsSnapshotForState = (clients: any): any => { | ||
| if (!clients || typeof clients !== "object") { | ||
| return undefined; | ||
| } | ||
| if (typeof clients.on === "function" || "state" in clients) { | ||
| return { state: clients.state }; | ||
| } | ||
|
|
||
| const snapshot: Record<string, any> = {}; | ||
| for (const key in clients) { | ||
| const childSnapshot = getClientsSnapshotForState(clients[key]); | ||
| if (childSnapshot !== undefined) { | ||
| snapshot[key] = childSnapshot; | ||
| } | ||
| } | ||
| return Object.keys(snapshot).length > 0 ? snapshot : undefined; | ||
| }; | ||
|
|
||
| const syncCommentClientsSnapshot = ( | ||
| publishSessionId: string, | ||
| accountId: string, | ||
| publication: any, | ||
| ) => { | ||
| const session = getPublishSession(publishSessionId); | ||
| if (session?.currentIndex === undefined) { | ||
| return; | ||
| } | ||
|
|
||
| const snapshot = getClientsSnapshotForState(publication?.clients); | ||
| accountsStore.setState(({ accountsComments }) => | ||
| maybeUpdateAccountComment(accountsComments, accountId, session.currentIndex, (ac, acc) => { | ||
| const updatedAccountComment = { ...acc }; | ||
| if (snapshot === undefined) { | ||
| delete updatedAccountComment.clients; | ||
| } else { | ||
| updatedAccountComment.clients = snapshot; | ||
| } | ||
| ac[session.currentIndex] = updatedAccountComment; | ||
| }), | ||
| ); | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify test coverage for the new helper functions by checking if tests exercise the publishComment flow with clients state changes.
echo "=== Checking for tests that exercise publishComment with clients ==="
rg -n -C5 'publishComment|clients|statechange' --type=ts src/stores/accounts/accounts-actions.test.ts | head -100
echo ""
echo "=== Checking for direct tests of getClientsSnapshotForState (if exported elsewhere) ==="
rg -n 'getClientsSnapshotForState' --type=ts
echo ""
echo "=== Checking for syncCommentClientsSnapshot references in tests ==="
rg -n 'syncCommentClientsSnapshot' --type=tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 4548
🏁 Script executed:
# Get the publishComment tests and their assertions
sed -n '565,620p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 2030
🏁 Script executed:
# Also check around line 604 for the other publishComment test
sed -n '590,640p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1985
🏁 Script executed:
# Search for any test that specifically mentions or checks 'clients' in the test file
rg -n 'clients' src/stores/accounts/accounts-actions.test.ts -A3 -B3Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 2501
🏁 Script executed:
# Look at the assertions in the clients-related tests
sed -n '2021,2084p' src/stores/accounts/accounts-actions.test.ts | tail -60Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 2512
🏁 Script executed:
# Check the other clients tests assertions
sed -n '2086,2150p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 2823
🏁 Script executed:
# Check if there are any assertions about clients being present/absent in the stored comments
rg -n 'expect.*clients' src/stores/accounts/accounts-actions.test.ts -B5 -A2Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
🏁 Script executed:
# Look at the complete test for clients.ipfsGateways to see all assertions
sed -n '2121,2160p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1867
🏁 Script executed:
# Search for any assertion that checks whether clients are present or absent in stored comments
rg -n 'clients' src/stores/accounts/accounts-actions.test.ts | grep -i 'expect\|assert\|undefined\|delete'Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
🏁 Script executed:
# Check the full content of the test to see what it actually asserts about clients
sed -n '2121,2155p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1748
🏁 Script executed:
# Check if there's any verification of the comment structure stored in accountsComments
rg -n 'accountsComments' src/stores/accounts/accounts-actions.test.ts -A2 -B2 | head -80Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 3603
🏁 Script executed:
# Check what assertions exist in the clients edge case test (after the state clear/emit)
sed -n '2086,2125p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1833
🏁 Script executed:
# Also check the chainProviders test for assertions
sed -n '2021,2055p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1588
🏁 Script executed:
# Check if there are any tests that specifically verify clients is NOT in the stored comment
rg -n 'NOT.*clients|!.*clients|undefined.*clients|delete.*clients' src/stores/accounts/accounts-actions.test.ts -B3 -A3Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
🏁 Script executed:
# Check for any assertions after the setTimeout in the chainProviders test
sed -n '2021,2080p' src/stores/accounts/accounts-actions.test.ts | tail -40Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 1851
🏁 Script executed:
# Search for tests that specifically check what's NOT in the stored comment (clients should be removed or transformed)
rg -n 'toEqual|toStrictEqual' src/stores/accounts/accounts-actions.test.ts | grep -i 'client\|comment' -B2 -A2Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
🏁 Script executed:
# Get the full test file size and look for all test names containing "client"
wc -l src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 127
🏁 Script executed:
# Find all test names related to clients
rg -n 'test\(' src/stores/accounts/accounts-actions.test.ts | grep -i 'client'Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 508
🏁 Script executed:
# Check what the storedComment structure looks like in tests - does it verify clients?
sed -n '1345,1365p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 975
🏁 Script executed:
# Look at the line where getClientsSnapshotForState is used at line 1202
sed -n '1195,1210p' src/stores/accounts/accounts-actions.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1062
🏁 Script executed:
# Check if any test verifies the clients property in stored comments
rg -n '\\.clients' src/stores/accounts/accounts-actions.test.ts -B2 -A2Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
🏁 Script executed:
# Check if there are any test assertions that validate the clients snapshot behavior
rg -n 'expect.*storedComment' src/stores/accounts/accounts-actions.test.ts | head -20Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 487
🏁 Script executed:
# Look for tests that specifically verify clients property in stored comment
rg -n 'storedComment.*clients|clients.*stored' src/stores/accounts/accounts-actions.test.ts -B3 -A3Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
🏁 Script executed:
# Check the full test around line 2121 to see all its assertions
sed -n '2121,2160p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1867
🏁 Script executed:
# Check if there are any assertions inside the client tests that we might have missed
sed -n '2021,2084p' src/stores/accounts/accounts-actions.test.ts | grep -n 'expect\|assert'Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 114
🏁 Script executed:
# Check the full chainProviders test to see if it has any assertions we missed
sed -n '2021,2055p' src/stores/accounts/accounts-actions.test.tsRepository: bitsocialnet/bitsocial-react-hooks
Length of output: 1588
🏁 Script executed:
# Look for any test that validates the snapshot behavior or clients structure
rg -n 'getClientsSnapshot|snapshot' src/stores/accounts/accounts-actions.test.ts -B2 -A2Repository: bitsocialnet/bitsocial-react-hooks
Length of output: 60
Add assertions to verify getClientsSnapshotForState snapshot behavior in tests.
The three publishComment tests that exercise clients (chainProviders, ipfsGateways, clientsOnStateChange) have no assertions verifying the snapshot transformation. Tests at lines 2021, 2086, and 2121 run publishComment with clients but don't assert on the resulting stored client snapshot. Add assertions to verify that:
- Clients are properly snapshotted and stored in
accountsComments - Undefined clients are handled correctly (deleted from stored comment)
- The snapshot transformation works for nested clients structures
This is required per coding guidelines: mandatory 100% test coverage for stores must include verification of function behavior, not just execution of code paths.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/stores/accounts/accounts-actions.ts` around lines 62 - 102, Add
assertions in the three publishComment tests that exercise clients to validate
getClientsSnapshotForState behavior: after calling publishComment, read
accountsStore.getState().accountsComments and locate the stored comment for the
publish session index (use getPublishSession(publishSessionId).currentIndex or
the same index used in the test) and assert (1) when publication.clients
contains client objects with state/on, the accountsComments entry for that index
contains a clients snapshot equal to the expected shape produced by
getClientsSnapshotForState; (2) when publication.clients yields no snapshot
(getClientsSnapshotForState returns undefined), the stored comment has no
clients key (clients was deleted by syncCommentClientsSnapshot); and (3) for
nested client structures, assert the nested keys map to snapshots (state
objects) matching the transformation. Reference getClientsSnapshotForState,
syncCommentClientsSnapshot and maybeUpdateAccountComment to locate where to
assert stored results in accountsStore.
Deepens account comment compaction for existing users by rewriting legacy stored comments without runtime transport payloads, while keeping full history and first-party app behavior intact.
Closes #45
Note
Medium Risk
Touches comment persistence and IndexedDB migration logic; mistakes could drop or reorder users’ stored comment history even though tests cover common legacy scenarios.
Overview
Account comments are now compacted more aggressively in storage:
sanitizeStoredAccountCommentdrops runtime-only fields (e.g.clients,raw,replies.pages) and stores anoriginalsnapshot only for edited comments (in a reduced, renderable form).Live pending-comment state is preserved by introducing
sanitizeAccountCommentForState(keeps renderable fields while dropping heavy payloads) and by snapshottingcomment.clientsinto a state-safe shape during publishing so gateway/provider state updates don’t break pending comments.IndexedDB comment storage migrates to v2:
ensureAccountCommentsDatabaseLayoutrewrites legacy entries through the new sanitizer, removes sparse/undefined slots, and updateslengthaccordingly; tests expand coverage for export/read/delete migration and sparse-slot densification.Written by Cursor Bugbot for commit 3cdb706. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Tests
Refactor
Chores