// test/helpers/docker-services.js import { execSync } from 'node:child_process'; const RELAY_URL = 'http://localhost:2470'; const PLC_URL = 'http://localhost:2582'; const MINIO_URL = 'http://localhost:9000'; const USE_S3 = process.env.BLOB_STORAGE === 's3'; /** * Wait for a service to respond * @param {string} url * @param {string} name * @param {number} maxAttempts */ async function waitForService(url, name, maxAttempts = 30) { for (let i = 0; i < maxAttempts; i++) { try { const res = await fetch(url); if (res.ok) { console.log(`${name} is ready`); return; } } catch { // Service not ready yet } await new Promise((r) => setTimeout(r, 1000)); } throw new Error(`${name} failed to start after ${maxAttempts} attempts`); } /** * Ensure docker-compose services are running * Always resets volumes for clean state each test run */ export async function ensureDockerServices() { console.log('Resetting docker services for clean state...'); // Always reset volumes to avoid stale relay subscriptions execSync('docker compose down -v', { stdio: 'inherit' }); execSync('docker compose up -d', { stdio: 'inherit' }); // Wait for services to be ready await waitForService(PLC_URL, 'PLC'); await waitForService(RELAY_URL, 'Relay'); if (USE_S3) { await waitForService(`${MINIO_URL}/minio/health/ready`, 'MinIO'); } // Configure relay to accept new PDS subscriptions // Fresh relay database defaults perDayLimit to 0, blocking all subscriptions await configureRelayLimits(); console.log('Docker services are ready'); } /** * Configure relay rate limits for local testing * Sets perDayLimit to allow new PDS subscriptions */ async function configureRelayLimits() { const res = await fetch(`${RELAY_URL}/admin/subs/setPerDayLimit?limit=1000`, { method: 'POST', headers: { Authorization: 'Bearer localdev', }, }); if (!res.ok) { throw new Error(`Failed to configure relay limits: ${res.status}`); } console.log('Relay configured for local testing'); } /** * Request the relay to crawl a PDS * @param {string} hostname - PDS hostname (e.g., 'host.docker.internal:3000') */ export async function requestRelayCrawl(hostname) { const res = await fetch(`${RELAY_URL}/admin/pds/requestCrawl`, { method: 'POST', headers: { Authorization: 'Bearer localdev', 'Content-Type': 'application/json', }, body: JSON.stringify({ hostname }), }); if (!res.ok) { throw new Error(`Failed to request crawl: ${res.status}`); } } export { RELAY_URL, PLC_URL, MINIO_URL, USE_S3 };