Skip to content

Pin docs script tags and accept experiment_id in datapipe-client - #272

Merged
jodeleeuw merged 5 commits into
testfrom
fix/docs-pin-cdn-versions
Sep 22, 2026
Merged

jodeleeuw merged 5 commits into
testfrom
fix/docs-pin-cdn-versions

Conversation

@jodeleeuw

@jodeleeuw jodeleeuw commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Fixes three issues reported after launch, the third from #273.

Pin the script tags in the samples

The docs told researchers to load https://unpkg.com/datapipe-client and https://unpkg.com/@jspsych/extension-pipe with no version. unpkg serves the newest release for an unpinned URL, so publishing one could change a study that is already collecting data.

  • All 9 tags (the code panel plus the sending-data page) now come from components/dashboard/script-tags.js, pinned to extension-pipe 0.2.0 and datapipe-client 0.1.0.
  • The sending-data page explains why the version is pinned. The client README pins too.
  • The client's pin follows each release with no manual step:
    • Docs samples: script-tags.js reads the version from packages/client/package.json, so the release PR's version bump moves the pin.
    • README: version-packages now runs scripts/sync-readme-pin.mjs after changeset version to rewrite the pin. The script fails if the README has no unpkg URL to pin.
    • Why not one sync script for both: changesets/action (with cwd: packages/client) commits only files under that directory, so a script edit to components/ would never reach the release PR.
  • __tests__/script-tags.test.js catches either pin coming unstuck.
  • The extension's version lives in the jsPsych repo, so it's bumped by hand.

experiment_id in datapipe-client

The extension and the plugin call the experiment ID experiment_id. The client called it experimentID, and the streaming page switched between the two without comment.

  • The client now accepts experiment_id. experimentID keeps working, because studies on the old unpinned tag pass it and so does the extension.
  • If both are given and differ, saveData, saveBase64Data and getCondition throw before sending anything, and a session starts inert with a console warning. TypeScript rejects passing both, or neither.
  • The request body sent to the server is unchanged.
  • A changeset makes this a minor release, 0.2.0.

The samples and README use experiment_id, and the notes saying the two names differ are gone.

Pass the session to saveData

The documented streaming pattern was flush, read sessionId, submit. The flush was there only to wait for the session to start, but it also waited on the last staged write. A backgrounded tab throttles that write hard, so the final submission could sit for most of a minute (#273).

  • session.ready() resolves once the session has started, or failed to start. It never rejects, and it waits only for the /api/session round trip.
  • saveData({ session }) awaits ready() and sends the session's id. sessionId still works for callers who build the request themselves.
  • The README, the dashboard's Save-as-you-go sample and the streaming page show the new pattern, and the "flush before reading sessionId" warnings are gone.
  • Skipping the flush loses nothing. The final submission carries every trial, and a staged write that lands after it is refused, because the submission deletes openSessions/{id}.
  • Covered by the same 0.2.0 changeset release.

Release order

The samples, the README and the dashboard now use experiment_id and session, which only 0.2.0 understands. The script tags take their version from packages/client/package.json, which stays at 0.1.0 until the "Release datapipe-client" PR (opened by the test→main merge) bumps it. Merge that release PR right after test→main. Until it merges, prod serves 0.2.0 samples against a 0.1.0 tag.

Testing

  • Client: all 66 vitest tests pass (new cases cover both names, the conflict, ready() resolving while a staged write never lands, and saveData waiting on a session), tsc passes, and the build succeeds.
  • App: the new script-tags suite passes, as do extension-snippet, docs-nav and live-sessions-page. Lint is clean.
  • next build passes, and the prerendered sending-data page loads datapipe-client@0.1.0.
  • Ran sync-readme-pin.mjs against a scratch copy with a bumped version. It pins an unpinned URL, leaves a pinned one alone, and exits 1 when there's no URL to pin.
  • All three pinned unpkg URLs return 200.

🤖 Generated with Claude Code

jodeleeuw and others added 5 commits September 21, 2026 18:30
An unpinned unpkg URL serves the newest release, so publishing one could
change a study that is already collecting data. Every sample now takes its
tag from components/dashboard/script-tags.js, pinned to extension-pipe
0.2.0 and datapipe-client 0.1.0, and the client README pins too.
__tests__/script-tags.test.js fails when the client pin falls behind
packages/client/package.json.

Also say on the streaming and sending-data pages that the library takes
experimentID while the extension's parameter is experiment_id.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The jsPsych extension and plugin call the experiment ID experiment_id, so
the client now takes that name too. experimentID keeps working, because
studies on an unpinned script tag pass it and so does the extension. If
both are given and differ, the one-shot calls throw and a session starts
inert with a warning. The wire format is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The docs samples now read datapipe-client's version from its package.json,
so the release PR's version bump moves their pin. That can't be done by a
sync script: changesets/action (cwd: packages/client) commits only files
under that directory, so an edit to components/ would never be committed.

The README is inside the package, so `version-packages` now runs
scripts/sync-readme-pin.mjs after `changeset version` to rewrite its pin.
The script fails if the README has no unpkg URL to pin, rather than
shipping one that points at the previous release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The documented pattern was flush, read sessionId, submit. The flush was
only there to wait for the session to start, but it also waited on the
last staged write, which a backgrounded tab throttles hard, so the final
submission could sit for most of a minute (#273).

session.ready() waits for startup alone. saveData({ session }) awaits it
and sends the id, so callers no longer read sessionId themselves. The
sessionId option still works. The README, the dashboard sample and the
streaming docs now show the new pattern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The client accepts experiment_id as of this release, so the samples and
README now use the same name as the jsPsych extension, and the notes
explaining that the two names differ are gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jodeleeuw
jodeleeuw merged commit af99310 into test Sep 22, 2026
2 checks passed
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