Step 4 of 6 for the survey2ddi retirement. Plan: HANDOVER_SURVEY2DDI.md. Depends on the normalize_responses port for its transform subcommand; the list / pull half is independent.
Why
limesurvey2ddi in CorrelAid/survey2ddi pulls a survey's structure and responses over LimeSurvey's RemoteControl API and converts them. The conversion is duplicated here; the pull is not.
What to port
limesurvey2ddi/client.py + lstsv.py:
- JSON-RPC over RemoteControl (
/admin/remotecontrol): get_session_key → calls → release_session_key. RPC errors come back in the result body, not as HTTP status codes — the error shape and session expiry are the parts that need care, and the reason this is a bigger issue than the Kobo one.
list_surveys(), get_responses(survey_id), and the survey-structure TSV export that feeds lstsvToDdiXml.
pull(survey_id, out) writing the structure TSV + responses.
CLI:
formtransform limesurvey list
formtransform limesurvey pull <survey_id> -o output/
formtransform limesurvey transform <survey_id> -o output/ # pull + lstsv2ddi + data CSV
Env vars keep their current names so existing .env files work: LIME_SERVER_URL, LIME_USERNAME, LIME_PASSWORD, each overridable by a flag.
Prior art in this repo
tests/live/ already drives this exact API — through the citric Python client, via codegen.limesurvey_stack (session handling, wait_until_ready, import+activate). Read that for the call sequence before writing the RPC layer.
Worth deciding as part of this issue: once a TS client exists, should the live suite exercise it instead of citric? That would make the client's session handling continuously tested against a real LimeSurvey rather than only in unit tests with mocked responses. Not required to close this, but say which way you went and why.
Constraints
- Node-only; not re-exported from
src/index.ts (same rule as the Kobo adapter).
- Never log credentials or the session key.
- Always release the session key, including on error paths.
Acceptance criteria
Step 4 of 6 for the survey2ddi retirement. Plan:
HANDOVER_SURVEY2DDI.md. Depends on thenormalize_responsesport for itstransformsubcommand; thelist/pullhalf is independent.Why
limesurvey2ddiinCorrelAid/survey2ddipulls a survey's structure and responses over LimeSurvey's RemoteControl API and converts them. The conversion is duplicated here; the pull is not.What to port
limesurvey2ddi/client.py+lstsv.py:/admin/remotecontrol):get_session_key→ calls →release_session_key. RPC errors come back in the result body, not as HTTP status codes — the error shape and session expiry are the parts that need care, and the reason this is a bigger issue than the Kobo one.list_surveys(),get_responses(survey_id), and the survey-structure TSV export that feedslstsvToDdiXml.pull(survey_id, out)writing the structure TSV + responses.CLI:
Env vars keep their current names so existing
.envfiles work:LIME_SERVER_URL,LIME_USERNAME,LIME_PASSWORD, each overridable by a flag.Prior art in this repo
tests/live/already drives this exact API — through thecitricPython client, viacodegen.limesurvey_stack(session handling,wait_until_ready, import+activate). Read that for the call sequence before writing the RPC layer.Worth deciding as part of this issue: once a TS client exists, should the live suite exercise it instead of
citric? That would make the client's session handling continuously tested against a real LimeSurvey rather than only in unit tests with mocked responses. Not required to close this, but say which way you went and why.Constraints
src/index.ts(same rule as the Kobo adapter).Acceptance criteria
list/pull/transformmatch the Python CLI's behaviour and env varstests/live/now uses the TS client