#!/usr/bin/env nu use common.nu * def test-repos-pagination [url: string] { print "verifying /repos pagination..." print " testing limit=1..." let items = (http get $"($url)/repos?limit=1" | from json -o) if ($items | length) != 1 { fail "expected 1 item with limit=1" } print $" count: ($items | length)" let all_items = (http get $"($url)/repos" | from json -o) print $" count: ($all_items | length)" if ($all_items | length) > 1 { let first_did = ($all_items | get 0).did print $" testing cursor with did ($first_did)..." let cursor_items = (http get $"($url)/repos?cursor=($first_did)&limit=1" | from json -o) if ($cursor_items | length) > 0 { let next_did = ($cursor_items | get 0).did if $first_did == $next_did { fail "cursor did should be excluded from results" } print $" next did: ($next_did)" } } print "/repos pagination passed!" } def test-repos-validation-errors [url: string] { print "verifying /repos error handling..." print " testing PUT /repos with invalid DID..." http put -f -e -t application/json $"($url)/repos" [{ did: "invalid" }] | assert-status 400 "PUT /repos invalid DID" print " testing DELETE /repos with invalid DID..." http delete -f -e -t application/json $"($url)/repos" --data [{ did: "invalid" }] | assert-status 400 "DELETE /repos invalid DID" print " testing GET /repos with invalid cursor..." http get -f -e $"($url)/repos?cursor=invalid" | assert-status 400 "GET /repos invalid cursor" print "/repos validation errors passed!" } def test-body-deletion-routes [url: string, did: string] { print "verifying operator body deletion routes..." let record_url = $"($url)/repos/($did)/records/app.bsky.feed.post/3kzbif5moe22m" http delete -f -e $record_url | assert-status 400 "record deletion requires target" http delete -f -e $"($record_url)?target=nope" | assert-status 400 "record deletion rejects invalid target" let record_report = (http delete $"($record_url)?target=all") if $record_report.heads_redacted != 0 or $record_report.history_redacted != 0 { fail "empty record deletion should be idempotent" } http delete -f -e $"($url)/repos/not-a-did" | assert-status 400 "repo drop rejects invalid DID" let repo_report = (http delete $"($url)/repos/($did)") if $repo_report.heads_redacted != 0 or $repo_report.history_redacted != 0 { fail "empty repo drop should be idempotent" } let info = (http get $"($url)/repos/($did)") if $info.tracked { fail "repo drop should untrack the DID" } print "operator body deletion routes passed!" } def main [] { let port = resolve-test-port 3001 let url = $"http://localhost:($port)" let db_path = (mktemp -d -t hydrant_repos_api.XXXXXX) print $"starting hydrant for /repos API verification..." let binary = build-hydrant let instance = (with-env { HYDRANT_MODE: "filter" } { start-hydrant $binary $db_path $port }) if not (wait-for-api $url) { fail "hydrant did not start" $instance.pid } let dids = [ "did:plc:dfl62fgb7wtjj3fcbb72naae" "did:plc:q6gjnv26m4ay3m42ojvzx2m4" ] http put -t application/json $"($url)/repos" ($dids | each { |d| { did: $d } }) test-repos-pagination $url test-repos-validation-errors $url test-body-deletion-routes $url ($dids | first) kill $instance.pid }