#!/usr/bin/env tsx /** * Boots a local AT Protocol network (PDS + PLC) with an in-process Jetstream * emitter, creates test accounts, and auto-seeds dev fixtures into local.db. * * The network is ephemeral — PDS/PLC state is not persisted across restarts. * * Usage: * pnpm run dev:network */ import { createDevNetwork } from "./lib/dev-network-boot"; import { ensureDevAccounts } from "./lib/ensure-dev-accounts"; import { runDevSeed } from "./lib/run-dev-seed"; import { startDevJetstreamEmitter } from "./dev-jetstream-emitter"; const APP_URL = process.env.APP_URL || "http://[::1]:3000"; const JETSTREAM_PORT = process.env.JETSTREAM_PORT || "2480"; const ACCOUNTS = [ { shortName: "alice", handle: "alice.test", email: "alice@test.com", password: "alice-pass-123", displayName: "Alice Test", }, { shortName: "bob", handle: "bob.test", email: "bob@test.com", password: "bob-pass-123", displayName: "Bob Test", }, { shortName: "carol", handle: "carol.test", email: "carol@test.com", password: "carol-pass-123", displayName: "Carol Blocked", }, { shortName: "dave", handle: "dave.test", email: "dave@test.com", password: "dave-pass-123", displayName: "Dave Suspended", }, { shortName: "askimut", handle: "askimut.test", email: "askimut@test.com", password: "askimut-pass-123", displayName: "Askimut Service", }, ]; async function main() { console.log("Starting local AT Protocol network...\n"); const network = await createDevNetwork(); const pdsUrl = network.pds.url; const plcUrl = network.plc.url; console.log(`PDS running at: ${pdsUrl}`); console.log(`PLC running at: ${plcUrl}`); console.log(`DEV_PDS_URL=${pdsUrl}`); console.log(`DEV_PLC_URL=${plcUrl}\n`); console.log("Starting Jetstream emitter...\n"); const emitter = await startDevJetstreamEmitter({ pdsUrl, plcUrl, port: Number(JETSTREAM_PORT), }); const jetstreamUrl = emitter.url; console.log(`JETSTREAM_URL=${jetstreamUrl}\n`); const dids = await ensureDevAccounts(network, ACCOUNTS); await network.processAll(); console.log("Seeding dev fixtures...\n"); await runDevSeed({ pdsUrl, plcUrl }); const bar = "═".repeat(60); console.log(`\n${bar}`); console.log(` Open the app at: ${APP_URL}`); console.log(` Jetstream emitter at: ${jetstreamUrl}`); console.log(`${bar}`); console.log( " IMPORTANT: use exactly this URL (IPv6 loopback). Opening\n" + " http://localhost:3000 or http://127.0.0.1:3000 will break the\n" + " OAuth flow — the PDS rejects same-site authorize requests.\n", ); console.log("--- Test accounts ---\n"); for (const account of ACCOUNTS) { const did = dids[account.shortName]; console.log(` ${account.handle}`); console.log(` DID: ${did}`); console.log(` Email: ${account.email}`); console.log(` Password: ${account.password}`); console.log(""); } console.log("Network is running. Press Ctrl+C to stop.\n"); const shutdown = async () => { console.log("\nShutting down..."); await emitter.close(); await network.close(); process.exit(0); }; process.on("SIGINT", () => void shutdown()); process.on("SIGTERM", () => void shutdown()); await new Promise(() => {}); } main().catch((err) => { console.error("Fatal error:", err); process.exit(1); });