import test from "node:test"; import assert from "node:assert/strict"; import { access, mkdtemp, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { execFile, spawn } from "node:child_process"; import { promisify } from "node:util"; try { await access(".output/server/index.mjs"); } catch { await promisify(execFile)("npm", ["run", "build"], { stdio: "inherit" }); } const port = 19000 + Math.floor(Math.random() * 500); const storage = await mkdtemp(join(tmpdir(), "quickdrop-http-")); const child = spawn(process.execPath, [".output/server/index.mjs"], { env: { ...process.env, NITRO_HOST: "127.0.0.1", NITRO_PORT: String(port), AUTH_PASSCODE: "smoke-passcode", AUTH_SECRET: "smoke-secret-for-tests", QUICKDROP_STORAGE_DIR: storage, }, stdio: "ignore", }); async function request(url, init) { return fetch(`http://127.0.0.1:${port}${url}`, init); } async function waitForServer() { for (let attempt = 0; attempt < 50; attempt++) { try { const response = await request("/api/auth/session"); if (response.status === 200) return; } catch {} await new Promise((resolve) => setTimeout(resolve, 100)); } throw new Error("built server did not start"); } test("built server enforces auth and serves capability-only lease/chunk APIs", async () => { try { await waitForServer(); const reservationBody = JSON.stringify({ version: 2, chunkSize: 8 * 1024 * 1024, chunkCount: 1, noncePrefix: "AQIDBAUGBwg", expiresIn: "24h", maxReads: 1, }); assert.equal( ( await request("/api/drops", { method: "POST", headers: { "content-type": "application/json" }, body: reservationBody, }) ).status, 401, ); const login = await request("/api/auth/login", { method: "POST", headers: { "content-type": "application/json", origin: `http://127.0.0.1:${port}`, }, body: JSON.stringify({ passcode: "smoke-passcode" }), }); assert.equal(login.status, 204); const cookie = login.headers.get("set-cookie").split(";", 1)[0]; const reserve = await request("/api/drops", { method: "POST", headers: { "content-type": "application/json", cookie, origin: `http://127.0.0.1:${port}`, }, body: reservationBody, }); assert.equal(reserve.status, 201); const created = await reserve.json(); const chunk = new Uint8Array(16); const put = await request(`/api/drops/${created.id}/chunks/0`, { method: "PUT", headers: { "content-type": "application/octet-stream", cookie, origin: `http://127.0.0.1:${port}`, }, body: chunk, }); assert.equal(put.status, 201); const finalize = await request(`/api/drops/${created.id}/finalize`, { method: "POST", headers: { "content-type": "application/octet-stream", cookie, origin: `http://127.0.0.1:${port}`, }, body: new Uint8Array(17), }); assert.equal(finalize.status, 200); const descriptor = await request(`/api/drops/${created.id}`, { headers: { "x-quickdrop-access": created.access }, }); assert.equal(descriptor.status, 200); const first = await request(`/api/drops/${created.id}/leases`, { method: "POST", headers: { "x-quickdrop-access": created.access }, }); assert.equal(first.status, 201); const lease = await first.json(); const second = await request(`/api/drops/${created.id}/leases`, { method: "POST", headers: { "x-quickdrop-access": created.access }, }); assert.equal(second.status, 410); const reused = await request(`/api/drops/${created.id}/leases`, { method: "POST", headers: { "x-quickdrop-access": created.access, authorization: `Bearer ${lease.token}`, }, }); assert.equal(reused.status, 200); assert.equal((await reused.json()).token, lease.token); const chunkGet = await request(`/api/drops/${created.id}/chunks/0`, { headers: { authorization: `Bearer ${lease.token}` }, }); assert.equal(chunkGet.status, 200); assert.equal((await chunkGet.arrayBuffer()).byteLength, 16); const complete = await request(`/api/drops/${created.id}/complete`, { method: "POST", headers: { authorization: `Bearer ${lease.token}` }, }); assert.equal(complete.status, 204); // Completion retries must also be idempotent when the drop remains (unlimited reads). const unlimitedBody = JSON.stringify({ ...JSON.parse(reservationBody), maxReads: null, }); const unlimitedReserve = await request("/api/drops", { method: "POST", headers: { "content-type": "application/json", cookie, origin: `http://127.0.0.1:${port}`, }, body: unlimitedBody, }); assert.equal(unlimitedReserve.status, 201); const unlimited = await unlimitedReserve.json(); assert.equal( ( await request(`/api/drops/${unlimited.id}/chunks/0`, { method: "PUT", headers: { "content-type": "application/octet-stream", cookie, origin: `http://127.0.0.1:${port}`, }, body: chunk, }) ).status, 201, ); assert.equal( ( await request(`/api/drops/${unlimited.id}/finalize`, { method: "POST", headers: { "content-type": "application/octet-stream", cookie, origin: `http://127.0.0.1:${port}`, }, body: new Uint8Array(17), }) ).status, 200, ); const unlimitedClaim = await request(`/api/drops/${unlimited.id}/leases`, { method: "POST", headers: { "x-quickdrop-access": unlimited.access }, }); assert.equal(unlimitedClaim.status, 201); const unlimitedLease = await unlimitedClaim.json(); const completionInit = { method: "POST", headers: { authorization: `Bearer ${unlimitedLease.token}` }, }; assert.equal( (await request(`/api/drops/${unlimited.id}/complete`, completionInit)) .status, 204, ); assert.equal( (await request(`/api/drops/${unlimited.id}/complete`, completionInit)) .status, 204, ); } finally { child.kill("SIGTERM"); await rm(storage, { recursive: true, force: true }); } });