Skip to content

feat(metadata,cli,frontend): accept { "trials": [...] } JSON wrapper#116

Open
Mandyx22 wants to merge 1 commit into
mainfrom
feat/unwrap-trials-wrapper
Open

feat(metadata,cli,frontend): accept { "trials": [...] } JSON wrapper#116
Mandyx22 wants to merge 1 commit into
mainfrom
feat/unwrap-trials-wrapper

Conversation

@Mandyx22

Copy link
Copy Markdown
Contributor

What & why

Some jsPsych data exports (e.g. from OSF) wrap the trials array as a single JSON object { "trials": [ … ] } instead of the bare array the pipeline expects. Every consumer parsed JSON then checked Array.isArray, so these files were silently skipped by the CLI/frontend (0 files read) and threw in the library — a confusing failure with no real error.

This makes all three packages accept the wrapper by unwrapping it before processing.

Approach

One shared helper, unwrapTrials, exported from @jspsych/metadata and used at every JSON parse site:

  • Unwraps the array only for an exact single-key { trials: [...] } wrapper.
  • Returns every other shape unchanged, so existing gates keep their behavior (library still throws on non-array; CLI/frontend still skip).
  • An object with sibling keys ({ trials: [...], meta: {...} }) is deliberately left untouched rather than silently discarding top-level metadata.

Wired into:

  • packages/metadata/src/index.tsgenerate() (throw preserved)
  • packages/cli/src/data.ts — pre-analysis, dry-run, and writer paths
  • packages/frontend/src/pages/DataUpload.tsx — join-key preflight + CSV writer

A wrapped file is converted to a Psych-DS data CSV (plus sidecars), and its literal wrapped original is still preserved byte-for-byte under data/raw/.

Tests — 339 pass across all 23 suites

  • New packages/metadata/tests/unwrap-trials.test.ts — helper edge cases (empty trials, non-array trials, sibling keys, null/primitive, pre-parsed input, malformed) + generate() wrapper-vs-bare-array equivalence + still-throws on non-array.
  • Extended packages/cli/tests/data.test.ts — wrapper → main CSV from unwrapped trials and byte-identical raw preservation; pre-analysis no longer skips; { trials: {} } still skipped.
  • New packages/frontend/tests/unwrapTrials.test.ts — guards the frontend's import/contract with the helper. (A full DataUpload render test was intentionally skipped: runGenerate calls generate(), which fetches plugins over the network — something no frontend test does. The end-to-end conversion is covered by the CLI suite, which shares the same helper and buildPsychDSDataFiles.)

E2E verification

Ran the CLI against the real OSF sample copied verbatim (still wrapped) as subj-1_data.json: "1 files read" (previously skipped), 9 trials → main CSV + 4 sidecars, data/raw/subj-1_data.json byte-identical to the original, and Psych-DS validation passed (warnings only).

Follow-up note

When the JSON-Lines ingestion work lands, its parsing path should reuse unwrapTrials so wrapper support is consistent across JSON and JSONL inputs (flagged with a TODO in the helper).

🤖 Generated with Claude Code

Some jsPsych exports (e.g. from OSF) wrap the trials array as a single
JSON object `{ "trials": [...] }` instead of a bare array. Every consumer
parsed JSON then checked `Array.isArray`, so these files were silently
skipped ("0 files read") by the CLI/frontend and threw in the library.

Add a shared `unwrapTrials` helper (exported from @jspsych/metadata) that
unwraps the array only for an exact single-key `{ trials: [...] }` wrapper
and returns every other shape unchanged, so existing gates keep their
behavior. An object with sibling keys (`{ trials, meta }`) is left
untouched rather than discarding top-level metadata.

generate(), the CLI directory pipeline, and the frontend uploader all
route JSON through the helper. A wrapped file is converted to a Psych-DS
data CSV (plus sidecars) and its literal wrapped original is still
preserved under data/raw/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 02ca494

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@jspsych/metadata Minor
@jspsych/metadata-cli Patch
frontend Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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