Skip to content

feat: Persist query params - #54

Open
livtanong wants to merge 11 commits into
mainfrom
persist-query-params
Open

feat: Persist query params#54
livtanong wants to merge 11 commits into
mainfrom
persist-query-params

Conversation

@livtanong

@livtanong livtanong commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Requires #52 to be merged

@livtanong
livtanong requested a review from d6e July 28, 2026 03:52
@livtanong
livtanong force-pushed the persist-query-params branch from f9770ed to 0793658 Compare July 28, 2026 04:04
@livtanong livtanong changed the title Persist query params feat: Persist query params Jul 28, 2026
d6e added 5 commits August 5, 2026 22:34
These fields were removed from IGeneVariant and IIndexMap, but the
fixtures still passed them, so pnpm run check failed with three errors.
Vitest strips types, so the tests kept passing and hid the breakage.
Iterator.prototype.map and toArray need Chrome 122, Firefox 131, or
Safari 18.4, and nothing in the build polyfills them. Below those
versions the call threw on every visit to the page, even with no query
string, which the catch turned into an alert about parsing a file that
the visitor had not selected.
The mps data comes from JSON.parse, so the in operator also matched
inherited keys. A link such as ?toString=A1 reached Object.prototype
and threw, which discarded every variant in the URL and left the
visitor with an alert and an empty table.
parseVCFData left flipStrand at its default, so a reverse-strand variant
read from a VCF was never normalized. The query params written from that
variant are re-read through IndexMap.parser, which does set the flag, so
the same genome gave one answer on upload and another after a reload.
For rs1801133 that is the difference between NO ATTN and ATTN:CT.

parseVCFData is no longer private so the round trip can be tested
without going through a 100 MB file.
The Genotype column read the raw genotype while Attention and
Interesting stayed in SNPedia orientation, so a reverse-strand row
showed a flagged allele that did not appear in the genotype next to it,
for example Genotype AG against ATTN:CT.
@d6e

d6e commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Reviewed and pushed five fixes to the branch.

  • d97be74 parseVCFData never set flipStrand, but the query params it writes get re-read through IndexMap.parser, which does. For rs1801133 the badge reads NO ATTN on upload and ATTN:CT after a reload. Needs a .vcf over 100 MB, so the Nebula path. Closes Add reverse strand handling for VCF #55.
  • c9b577d Genotype column showed the raw genotype while Attention and Interesting stayed in SNPedia orientation, so a reverse-strand row read Genotype AG against ATTN:CT. Now uses normalizedGenotype.
  • cce3f69 pnpm run check failed with three errors: two fixtures still passed chromosome/position. Vitest strips types, so the tests hid it.
  • ca131f1 entries().map(...).toArray() needs Safari 18.4. Below that it threw on every page visit, even with no query string, and the catch alerted about parsing a file nobody selected. Now Array.from.
  • 811ec32 snp in mpsDict matched inherited keys, so ?toString=A1 threw and discarded every other variant. Now Object.hasOwn.

The read-back is skipped. #43 specifies Upload File -> Parse -> Set Query Params -> Read Query Params -> Analyze -> Render, but onFileInput writes the params and then renders from the parsed variants directly. That shortcut is why upload and reload could disagree at all, and d97be74 only patches the one case where they did. Closing the loop the way #43 describes would rule out the whole class.

Query string vs fragment. Everything else here stays on the device, but a query string is sent to the server on any reload or shared link, so the genotypes end up in GitHub's request logs. A fragment (#rs1801133=AG&...) is never sent. Two lines: window.location.search becomes window.location.hash.slice(1), and ? becomes #. URLSearchParams parses the fragment body unchanged.

The notice ("no data is sent or stored elsewhere") only stays accurate with the fragment. It also needs a line saying results are in the address, since anyone with the link can read them and it sits in browser history.

@livtanong

livtanong commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

I'm so glad you're around to clean up my mess 😅 Thanks for the additional commits!

The read-back is skipped

Yeah, I decided to skip the read-back because it would cause a flicker as it reloaded the page. At the moment, the shortcut is the best compromise I can think of.

Persistence to the address bar is a side-effect of parsing a file, and the address bar is used to load state if there happens to be state in the query params.

Everything else here stays on the device, but a query string is sent to the server on any reload or shared link, so the genotypes end up in GitHub's request logs

I hadn't thought of this! The data isn't personally identifiable though, so the most that github can get is an odd census (with lots of repeated data) about the SNPs we're concerned about. I'll add additional explanation to the preamble.

@livtanong
livtanong requested a review from d6e August 8, 2026 03:29
@livtanong

Copy link
Copy Markdown
Collaborator Author

@d6e Updated the preamble. Not sure how to make this any less wordy without compromising meaningful nuance.

A query string is sent to the server on every reload and every visit to a
shared link, putting the genotypes in request logs. A fragment is never
put on the wire. URLSearchParams parses the fragment body unchanged, so
the round trip is otherwise identical.

This also restores the original notice, which 2e55643 had expanded only
to explain those request logs.
@d6e

d6e commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

After thinking about this more, I actually think we should just go with using a fragment (#) instead of a query (?) then we can avoid the problem altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants