Skip to content

fix(model-export): make model TSV download work (#221) - #228

Open
VibhavSetlur wants to merge 1 commit into
ModelSEED:stagingfrom
VibhavSetlur:fix/issue-221-model-tsv-export
Open

fix(model-export): make model TSV download work (#221)#228
VibhavSetlur wants to merge 1 commit into
ModelSEED:stagingfrom
VibhavSetlur:fix/issue-221-model-tsv-export

Conversation

@VibhavSetlur

Copy link
Copy Markdown
Collaborator

Fixes the actionable half of #221.

What was actually wrong

TSV download (real bug). The model Download menu offered a TSV entry that issued
GET /api/models/export?ref=…&format=tsv. The ModelSEED API only supports json, sbml and
cobrapy — verified live against https://modelseed.org/PMS/openapi.json:

Export a model in the specified format. Supported formats: json, sbml, cobrapy.

So that menu entry could never produce a file. Nothing in the repo tested it
(scripts/api-test.mjs and scripts/comprehensive-api-test.mjs only cover SBML and JSON).

SBML download (not a bug). The reporter's attached DC1RawModel.xml was downloaded and
checked: it is complete, well-formed SBML L3V1 + FBC v2 — 1100 <species>, 1127 <reaction>,
unit definitions, compartments, fbc:objective fbc:type="maximize", fbc:listOfGeneProducts,
properly closed </model></sbml>. The kbase_compartment_data / modelseed_template_id: cpdXXXX_c
lines they saw are the text of legal <notes><html><p>…</p></html></notes> blocks, which is what a
browser shows if it renders the file as HTML. No SBML change was made or needed — that file
should load in COBRA Toolbox / cobrapy as-is.

The fix

Build the tabular exports client-side from the supported format=json export, and split the one
dead entry into two working ones:

Menu entry Source File
SBML API format=sbml <model>.xml (unchanged)
JSON API format=json <model>.json (unchanged)
Reactions (TSV) derived from format=json <model>.reactions.tsv
Compounds (TSV) derived from format=json <model>.compounds.tsv

Columns follow the legacy rxntbl/cpdtbl shape the issue asks for:

  • reactions: id, direction, compartment, gpr, name, equation, pathways
  • compounds: id, name, formula, charge, compartment

compartment is derived from the id suffix (cpd00443_c0c0).

Changes

  • new lib/utils/modelTsv.ts — pure buildReactionsTsv / buildCompoundsTsv /
    compartmentFromId, reusing the existing RFC-4180 escaper in lib/utils/exportCsv.ts
    (no new escaping code, no new dependency).
  • components/ui/DownloadModelMenu.tsx — options moved to an exported, typed
    'api' | 'derived-tsv' discriminated union; downloadingFormatdownloadingKey.
    Props interface unchanged, so both call sites (model viewer and My Models) are unaffected.
  • lib/api/modelseed.ts — doc comment corrected; it still advertised a 'tsv' format. No
    behaviour change.
  • app/model/[...path]/page.tsx — helper text updated (one line).

Tests

  • tests/unit/utils/modelTsv.test.ts — header rows, compartment derivation, charge: 0 rendering
    as 0, commas in reaction names staying unquoted under a tab delimiter, missing optional fields
    keeping the full column count, pathway joining, and the empty-model error paths.
  • tests/unit/components/downloadModelMenuOptions.test.tsthe regression test that would have
    caught this
    : asserts every API-backed menu entry requests a format inside the backend's
    documented set ['json','sbml','cobrapy'], and that nothing requests tsv from the API.

Fixture shapes were taken from the reporter's own DC1RawModel.json, i.e. real production
format=json output.

Verification

All green locally, mirroring .github/workflows/ci.yml:

  • npm run lint — 0 errors (16 pre-existing warnings, none in changed files)
  • npx tsc --noEmit — clean
  • npm run test:run — 18 files, 145 tests passed (+18 new)
  • npm run build — compiled successfully, 31/31 static pages
  • npm audit --omit=dev --audit-level=high — 0 vulnerabilities

Notes for review

  • No version or CHANGELOG changes in this PR — deliberate; versioning is decided when
    staging is promoted to master.
  • format=cobrapy is documented by the API but was not added to the menu, because it could not
    be verified end-to-end without an auth token, and shipping an unverified format is exactly the
    bug this PR fixes. Easy follow-up once someone confirms it works.
  • The remaining part of Model download (SBML, cpdtbl) and reconstruction service unavailable after website update #221 ("reconstruction service unavailable", and native server-side
    TSV/cpdtbl export) is a backend concern for modelseed-api, not this repo.
  • Branched from staging; kept separate from the still-open feat(feedback): add homepage GitHub Issues link #227 so the two can be reviewed
    independently.

The model Download menu offered a "TSV" option that called
GET /api/models/export?format=tsv, but the ModelSEED API only supports
json | sbml | cobrapy (verified against https://modelseed.org/PMS/openapi.json).
The option therefore never produced a file.

Derive the tabular exports in the browser from the supported `format=json`
export instead, and split the single dead entry into two working ones:
"Reactions (TSV)" and "Compounds (TSV)". This gives users the cpdtbl/rxntbl
style tables requested in the issue.

- add lib/utils/modelTsv.ts with pure buildReactionsTsv/buildCompoundsTsv
  builders reusing the existing RFC-4180 escaper in lib/utils/exportCsv.ts
- rewire components/ui/DownloadModelMenu.tsx onto a discriminated
  'api' | 'derived-tsv' option union and export EXPORT_OPTIONS
- correct the stale exportModelFromApi doc comment that listed 'tsv'
- update the model page helper text
- add unit tests for the TSV builders plus a contract test asserting no
  menu entry requests a format outside the backend's supported set

Note: the issue also reported that the SBML download is not valid XML. The
reporter's own attachment parses as complete, well-formed SBML L3V1-FBCv2
(1100 species, 1127 reactions, fbc objective); the key/value text they saw is
the content of legal <notes> blocks. No SBML change was needed.
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.

1 participant